@phase2 @skills @agent_skills @agent_skills_loader Feature: Agent Skills Loader As a CleverAgents developer I want to load Agent Skills Standard SKILL.md folders into structured tool definitions So that actors can discover and invoke instruction-driven multi-step workflows # --------------------------------------------------------------------------- # AgentSkillSpec — SKILL.md Parsing # --------------------------------------------------------------------------- @agent_skill_parse Scenario: Parse a minimal SKILL.md with only required frontmatter fields Given a SKILL.md file with frontmatter: """ --- name: local/deploy-staging description: Deploy the current branch to the staging environment. --- Follow these steps to deploy. """ When I parse the SKILL.md file Then the parsed skill name should be "local/deploy-staging" And the parsed skill description should be "Deploy the current branch to the staging environment." And the parsed skill body should contain "Follow these steps to deploy." @agent_skill_parse Scenario: Parse a SKILL.md with all optional frontmatter fields Given a SKILL.md file with frontmatter: """ --- name: local/code-review description: Run a thorough code review checklist. version: 1.2.3 compatibility: min_agent_version: "3.0.0" metadata: author: aditya tags: [review, quality] allowed-tools: - local/read-file - local/search-files --- ## Code Review Steps 1. Check style 2. Verify tests """ When I parse the SKILL.md file Then the parsed skill name should be "local/code-review" And the parsed skill version should be "1.2.3" And the parsed skill allowed tools should include "local/read-file" And the parsed skill allowed tools should include "local/search-files" And the parsed skill metadata should have key "author" with value "aditya" @agent_skill_parse Scenario: Parse SKILL.md body text is preserved exactly Given a SKILL.md file with frontmatter: """ --- name: local/test-skill description: Test skill for body parsing. --- # Multi-line Instructions Step 1: Do something important. Step 2: Do another thing. ```python code_example() ``` """ When I parse the SKILL.md file Then the parsed skill body should contain "Step 1: Do something important." And the parsed skill body should contain "Step 2: Do another thing." And the parsed skill body should contain "code_example()" @agent_skill_parse @error_handling Scenario: SKILL.md missing required name field raises error Given a SKILL.md file with frontmatter: """ --- description: A skill without a name. --- Some body text. """ When I parse the SKILL.md file expecting an error Then the agent skill parse error should mention "name" @agent_skill_parse @error_handling Scenario: SKILL.md missing required description field raises error Given a SKILL.md file with frontmatter: """ --- name: local/no-desc --- Some body text. """ When I parse the SKILL.md file expecting an error Then the agent skill parse error should mention "description" @agent_skill_parse @error_handling Scenario: SKILL.md with invalid namespaced name raises error Given a SKILL.md file with frontmatter: """ --- name: invalid-name-no-slash description: A skill with a bad name. --- Body text. """ When I parse the SKILL.md file expecting an error Then the agent skill parse error should mention "namespace" @agent_skill_parse @error_handling Scenario: File without YAML frontmatter delimiter raises error Given a SKILL.md file with frontmatter: """ Just plain text without frontmatter. No YAML delimiter here. """ When I parse the SKILL.md file expecting an error Then the agent skill parse error should mention "frontmatter" @agent_skill_parse @error_handling Scenario: Empty SKILL.md file raises error Given an empty SKILL.md file When I parse the SKILL.md file expecting an error Then the agent skill parse error should mention "frontmatter" # --------------------------------------------------------------------------- # AgentSkillFolder — Folder Discovery # --------------------------------------------------------------------------- @agent_skill_folder Scenario: Discover a valid Agent Skills folder with SKILL.md Given an agent skills folder with a valid SKILL.md: """ --- name: local/folder-skill description: A skill loaded from a folder. --- Instructions here. """ When I load the agent skills folder Then the loaded agent skill name should be "local/folder-skill" And the loaded agent skill description should be "A skill loaded from a folder." @agent_skill_folder Scenario: Agent Skills folder discovers scripts/ subfolder Given an agent skills folder with a valid SKILL.md: """ --- name: local/scripted-skill description: A skill with bundled scripts. --- Use the scripts provided. """ And the folder contains a script file "deploy.py" with content "print('deploying')" When I load the agent skills folder Then the loaded agent skill script paths should include "deploy.py" @agent_skill_folder Scenario: Agent Skills folder discovers references/ subfolder Given an agent skills folder with a valid SKILL.md: """ --- name: local/ref-skill description: A skill with reference documents. --- See references/ for more. """ And the folder contains a reference file "guide.md" with content "# Guide" When I load the agent skills folder Then the loaded agent skill reference paths should include "guide.md" @agent_skill_folder Scenario: Agent Skills folder discovers assets/ subfolder Given an agent skills folder with a valid SKILL.md: """ --- name: local/asset-skill description: A skill with assets. --- See assets/ for resources. """ And the folder contains an asset file "template.json" with content "{}" When I load the agent skills folder Then the loaded agent skill asset paths should include "template.json" @agent_skill_folder Scenario: Agent Skills folder with no optional subfolders loads successfully Given an agent skills folder with a valid SKILL.md: """ --- name: local/bare-skill description: A minimal folder skill with no subfolders. --- Minimal instructions. """ When I load the agent skills folder Then the loaded agent skill script paths should be empty And the loaded agent skill reference paths should be empty And the loaded agent skill asset paths should be empty @agent_skill_folder @error_handling Scenario: Loading a folder without SKILL.md raises error Given an agent skills folder without a SKILL.md file When I load the agent skills folder expecting an error Then the agent skill load error should mention "SKILL.md" @agent_skill_folder @error_handling Scenario: Loading a non-existent folder raises error Given a non-existent agent skills folder path When I load the agent skills folder expecting an error Then the agent skill load error should mention "not found" # --------------------------------------------------------------------------- # Tool Mapping — AgentSkillSpec → ToolDescriptor # --------------------------------------------------------------------------- @agent_skill_tool_mapping Scenario: Agent skill maps to a tool with source agent_skill Given an agent skills folder with a valid SKILL.md: """ --- name: local/mapped-skill description: Maps to a tool descriptor. --- Do the task. """ When I load the agent skills folder And I convert the loaded agent skill to a tool descriptor Then the tool descriptor source should be "agent_skill" And the tool descriptor name should be "local/mapped-skill" @agent_skill_tool_mapping Scenario: Agent skill tool descriptor is read-only by default Given an agent skills folder with a valid SKILL.md: """ --- name: local/readonly-skill description: Should default to read-only. --- Read things. """ When I load the agent skills folder And I convert the loaded agent skill to a tool descriptor Then the tool descriptor should have read_only set to True And the tool descriptor should have writes set to False @agent_skill_tool_mapping Scenario: Agent skill tool descriptor includes allowed-tools in metadata Given an agent skills folder with a valid SKILL.md: """ --- name: local/allowed-tools-skill description: Skill with allowed tools declared. allowed-tools: - local/read-file - local/git-status --- Use allowed tools only. """ When I load the agent skills folder And I convert the loaded agent skill to a tool descriptor Then the tool descriptor allowed tools should include "local/read-file" And the tool descriptor allowed tools should include "local/git-status" @agent_skill_tool_mapping Scenario: Agent skill tool descriptor agent_skill_path points to folder Given an agent skills folder with a valid SKILL.md: """ --- name: local/path-skill description: Path should be captured in descriptor. --- Instructions. """ When I load the agent skills folder And I convert the loaded agent skill to a tool descriptor Then the tool descriptor agent_skill_path should be set # --------------------------------------------------------------------------- # Progressive Disclosure — Three-Tier Model # --------------------------------------------------------------------------- @progressive_disclosure Scenario: Discovery tier loads only metadata (name + description) Given an agent skills folder with a valid SKILL.md: """ --- name: local/disclosure-skill description: Progressive disclosure test skill. --- Full instructions that should only load on activate. Step 1: do this. Step 2: do that. """ When I call discover on the agent skill Then the discover result should have name "local/disclosure-skill" And the discover result should have description "Progressive disclosure test skill." And the discover result body should be empty @progressive_disclosure Scenario: Activation tier loads the full SKILL.md body Given an agent skills folder with a valid SKILL.md: """ --- name: local/activate-skill description: Activation loads the body. --- Step 1: do this. Step 2: do that. """ When I call discover on the agent skill And I call activate on the agent skill Then the activate result body should contain "Step 1: do this." And the activate result body should contain "Step 2: do that." @progressive_disclosure Scenario: Resource tier lists available scripts on demand Given an agent skills folder with a valid SKILL.md: """ --- name: local/resource-skill description: Resource tier test skill. --- Use the scripts. """ And the folder contains a script file "helper.py" with content "# helper" When I call discover on the agent skill And I list available resources Then the resources list should include "helper.py" @progressive_disclosure Scenario: Deactivation clears the loaded body Given an agent skills folder with a valid SKILL.md: """ --- name: local/deactivate-skill description: Deactivation clears body. --- Step 1: do this. """ When I call discover on the agent skill And I call activate on the agent skill And I call deactivate on the agent skill Then the agent skill body should be cleared # --------------------------------------------------------------------------- # Namespaced Naming # --------------------------------------------------------------------------- @agent_skill_naming Scenario: Skill with local namespace is accepted Given a SKILL.md file with frontmatter: """ --- name: local/my-skill description: A valid local skill. --- Body. """ When I parse the SKILL.md file Then the parsed skill name should be "local/my-skill" @agent_skill_naming Scenario: Skill with custom namespace is accepted Given a SKILL.md file with frontmatter: """ --- name: devops/deploy-pipeline description: A skill in the devops namespace. --- Body. """ When I parse the SKILL.md file Then the parsed skill name should be "devops/deploy-pipeline" @agent_skill_naming Scenario: Skill name with underscores and hyphens is accepted Given a SKILL.md file with frontmatter: """ --- name: local/my_complex-skill_v2 description: Valid name with mixed characters. --- Body. """ When I parse the SKILL.md file Then the parsed skill name should be "local/my_complex-skill_v2" @agent_skill_naming @error_handling Scenario: Skill name with special characters is rejected Given a SKILL.md file with frontmatter: """ --- name: local/bad name! description: Invalid name. --- Body. """ When I parse the SKILL.md file expecting an error Then the agent skill parse error should mention "namespace" # --------------------------------------------------------------------------- # Stable Step Ordering # --------------------------------------------------------------------------- @agent_skill_ordering Scenario: Steps in SKILL.md body are preserved in stable order Given a SKILL.md file with frontmatter: """ --- name: local/ordered-skill description: Ordered steps skill. --- Step A: First action. Step B: Second action. Step C: Third action. """ When I parse the SKILL.md file Then the parsed skill body steps should appear in order: "Step A", "Step B", "Step C" # --------------------------------------------------------------------------- # Folder path normalization and safety # --------------------------------------------------------------------------- @agent_skill_safety Scenario: Script paths are normalized to relative paths within the folder Given an agent skills folder with a valid SKILL.md: """ --- name: local/safe-skill description: Path normalization test. --- Use scripts. """ And the folder contains a script file "run.py" with content "# run" When I load the agent skills folder Then all script paths should be relative to the skill folder # --------------------------------------------------------------------------- # Edge case coverage — branch and statement completeness # --------------------------------------------------------------------------- @agent_skill_parse @error_handling @coverage Scenario: AgentSkillSpec.from_file on a non-existent path raises FileNotFoundError Given a non-existent SKILL.md path When I parse the non-existent SKILL.md file expecting an error Then the agent skill parse error should mention "SKILL.md" @agent_skill_parse @error_handling @coverage Scenario: SKILL.md with unclosed frontmatter delimiter raises error Given a SKILL.md file with frontmatter: """ --- name: local/unclosed-skill description: This frontmatter is never closed. """ When I parse the SKILL.md file expecting an error Then the agent skill parse error should mention "frontmatter" @agent_skill_parse @error_handling @coverage Scenario: SKILL.md with empty frontmatter block raises error Given a SKILL.md with an empty frontmatter block When I parse the SKILL.md file expecting an error Then the agent skill parse error should mention "frontmatter" @agent_skill_parse @error_handling @coverage Scenario: SKILL.md with malformed YAML in frontmatter raises error Given a SKILL.md with malformed YAML frontmatter When I parse the SKILL.md file expecting an error Then the agent skill parse error should mention "YAML" @agent_skill_parse @error_handling @coverage Scenario: SKILL.md with non-mapping YAML frontmatter raises error Given a SKILL.md with a YAML list as frontmatter instead of a mapping When I parse the SKILL.md file expecting an error Then the agent skill parse error should mention "mapping" @agent_skill_folder @coverage Scenario: AgentSkillLoader folder property returns resolved path Given an agent skills folder with a valid SKILL.md: """ --- name: local/prop-skill description: Property access test skill. --- Body text. """ When I load the agent skills folder Then the loaded agent skill folder property should be set @agent_skill_folder @error_handling @coverage Scenario: Loading a path that is a file not a directory raises error Given an agent skills folder path that is a file When I load the agent skills folder expecting an error Then the agent skill load error should mention "not a directory" @agent_skill_parse @coverage Scenario: SKILL.md with non-dict compatibility is handled gracefully Given a SKILL.md file with frontmatter: """ --- name: local/bad-compat description: Skill with non-dict compatibility field. compatibility: "just a string" --- Body text. """ When I parse the SKILL.md file Then the parsed skill name should be "local/bad-compat" @agent_skill_parse @coverage Scenario: SKILL.md with non-dict metadata is handled gracefully Given a SKILL.md file with frontmatter: """ --- name: local/bad-meta description: Skill with non-dict metadata field. metadata: "just a string" --- Body text. """ When I parse the SKILL.md file Then the parsed skill name should be "local/bad-meta" @agent_skill_folder @coverage Scenario: Sub-directories inside scripts/ are skipped during discovery Given an agent skills folder with a valid SKILL.md: """ --- name: local/nested-skill description: Skill with nested directories in scripts/. --- Use scripts. """ And the folder contains a script file "run.py" with content "# run" And the scripts folder contains a nested sub-directory When I load the agent skills folder Then the loaded agent skill script paths should include "run.py" And the loaded agent skill script paths should not include any directories @agent_skill_loader @error_handling @coverage Scenario: AgentSkillLoader constructor rejects None spec When I construct an AgentSkillLoader with None spec expecting an error Then the agent skill load error should mention "spec" @agent_skill_loader @error_handling @coverage Scenario: AgentSkillLoader constructor rejects None folder When I construct an AgentSkillLoader with None folder expecting an error Then the agent skill load error should mention "folder" @agent_skill_folder @error_handling @coverage Scenario: AgentSkillLoader.from_folder rejects None path When I call from_folder with None expecting an error Then the agent skill load error should mention "folder" # --------------------------------------------------------------------------- # Structured Steps — frontmatter steps list → SkillStep objects # --------------------------------------------------------------------------- @agent_skill_steps Scenario: SKILL.md with steps list in frontmatter parses into SkillStep objects Given a SKILL.md file with frontmatter: """ --- name: local/step-skill description: Skill with structured steps. steps: - Run tests to verify everything passes - Push branch to remote repository - Deploy to staging environment --- Detailed instructions go here. """ When I parse the SKILL.md file Then the parsed skill steps should have 3 entries And the parsed skill step 1 content should be "Run tests to verify everything passes" And the parsed skill step 2 content should be "Push branch to remote repository" And the parsed skill step 3 content should be "Deploy to staging environment" @agent_skill_steps Scenario: Structured steps maintain stable 1-based index ordering Given a SKILL.md file with frontmatter: """ --- name: local/ordered-steps-skill description: Ordered structured steps. steps: - Alpha step - Beta step - Gamma step --- Body text. """ When I parse the SKILL.md file Then the parsed skill step 1 index should be 1 And the parsed skill step 2 index should be 2 And the parsed skill step 3 index should be 3 @agent_skill_steps Scenario: SKILL.md without steps field has empty steps list Given a SKILL.md file with frontmatter: """ --- name: local/no-steps-skill description: Skill without steps field. --- Body text. """ When I parse the SKILL.md file Then the parsed skill steps should have 0 entries @agent_skill_steps @error_handling Scenario: SKILL.md with steps as a non-list raises actionable error Given a SKILL.md file with frontmatter: """ --- name: local/bad-steps-skill description: Skill with invalid steps field type. steps: "just a string instead of a list" --- Body text. """ When I parse the SKILL.md file expecting an error Then the agent skill parse error should mention "steps" @agent_skill_steps @error_handling Scenario: SKILL.md with an empty step entry raises actionable error Given a SKILL.md file with frontmatter: """ --- name: local/empty-step-skill description: Skill with an empty step in the list. steps: - First valid step - --- Body text. """ When I parse the SKILL.md file expecting an error Then the agent skill parse error should mention "steps" # --------------------------------------------------------------------------- # Resource Binding Slots — read-only slots for discovered directories # --------------------------------------------------------------------------- @agent_skill_resource_slots Scenario: Tool descriptor includes resource binding slots for discovered directories Given an agent skills folder with a valid SKILL.md: """ --- name: local/slotted-skill description: Skill with resource directories. --- Use scripts and references. """ And the folder contains a script file "run.py" with content "# run" And the folder contains a reference file "guide.md" with content "# Guide" When I load the agent skills folder And I convert the loaded agent skill to a tool descriptor Then the tool descriptor should have 2 resource slot(s) And the tool descriptor resource slot "scripts" should have access "read_only" And the tool descriptor resource slot "references" should have access "read_only" @agent_skill_resource_slots Scenario: Tool descriptor with no resource directories has empty resource slots Given an agent skills folder with a valid SKILL.md: """ --- name: local/no-slots-skill description: Skill with no resource directories. --- Instructions. """ When I load the agent skills folder And I convert the loaded agent skill to a tool descriptor Then the tool descriptor should have 0 resource slot(s) And the loaded skill resource_slots property should be empty @agent_skill_resource_slots Scenario: Discover descriptor includes resource binding slots Given an agent skills folder with a valid SKILL.md: """ --- name: local/discover-slots-skill description: Skill exposing slots at discover time. --- Instructions. """ And the folder contains an asset file "config.json" with content "{}" When I call discover on the agent skill Then the discover result should have 1 resource slot(s) And the discover result resource slot "assets" should have access "read_only"