249 lines
13 KiB
Gherkin
249 lines
13 KiB
Gherkin
Feature: Skill CLI coverage round 3
|
|
Cover remaining uncovered branches in src/cleveragents/cli/commands/skill.py:
|
|
tools --refresh flag, list/show non-rich capability error fallback,
|
|
refresh with agent_skills_paths discovery, refresh errors, long
|
|
description truncation, and the tools ValueError path.
|
|
|
|
Background:
|
|
Given r3skill- a fresh skill CLI service
|
|
|
|
# -------------------------------------------------------------------
|
|
# tools --refresh flag with agent_skills_paths configured (lines 815-838)
|
|
# -------------------------------------------------------------------
|
|
|
|
Scenario: Tools command with --refresh and configured agent_skills paths
|
|
Given r3skill- a registered skill "local/refreshable" with tool_refs
|
|
And r3skill- agent_skills_paths config resolves to a valid path with discovered skills
|
|
When r3skill- I invoke tools "local/refreshable" with --refresh
|
|
Then r3skill- the CLI exit code should be 0
|
|
And r3skill- the output should contain "Refreshed"
|
|
And r3skill- the output should contain "agent skill"
|
|
|
|
Scenario: Tools command with --refresh and empty agent_skills_paths
|
|
Given r3skill- a registered skill "local/no-agent-paths" with tool_refs
|
|
And r3skill- agent_skills_paths config resolves to empty string
|
|
When r3skill- I invoke tools "local/no-agent-paths" with --refresh
|
|
Then r3skill- the CLI exit code should be 0
|
|
|
|
Scenario: Tools command with --refresh and discovery errors
|
|
Given r3skill- a registered skill "local/disc-errors" with tool_refs
|
|
And r3skill- agent_skills_paths config resolves with discovery errors
|
|
When r3skill- I invoke tools "local/disc-errors" with --refresh
|
|
Then r3skill- the CLI exit code should be 0
|
|
And r3skill- the output should contain "Warning"
|
|
|
|
# -------------------------------------------------------------------
|
|
# tools ValueError path (lines 887-889)
|
|
# -------------------------------------------------------------------
|
|
|
|
Scenario: Tools command when resolve_tools raises ValueError
|
|
Given r3skill- a registered skill "local/val-err-tools" with tool_refs
|
|
And r3skill- resolve_tools will raise ValueError for "local/val-err-tools"
|
|
When r3skill- I invoke tools "local/val-err-tools" in rich format
|
|
Then r3skill- the CLI exit code should not be 0
|
|
And r3skill- the output should contain "Resolution error"
|
|
|
|
# -------------------------------------------------------------------
|
|
# list non-rich format: capability summary ValueError fallback (lines 667-669)
|
|
# -------------------------------------------------------------------
|
|
|
|
Scenario: List with JSON format falls back when capability summary raises ValueError
|
|
Given r3skill- a registered skill "local/cap-fallback" with tool_refs
|
|
And r3skill- compute_capability_summary will raise ValueError
|
|
When r3skill- I invoke list in format "json"
|
|
Then r3skill- the CLI exit code should be 0
|
|
And r3skill- the output should be valid JSON
|
|
And r3skill- the JSON list first item should have key "tool_count"
|
|
And r3skill- the JSON list first item "capability_summary" should be null
|
|
|
|
# -------------------------------------------------------------------
|
|
# show non-rich format: capability summary ValueError fallback (lines 764-766)
|
|
# -------------------------------------------------------------------
|
|
|
|
Scenario: Show with JSON format falls back when capability summary raises ValueError
|
|
Given r3skill- a registered skill "local/show-cap-err" with tool_refs
|
|
And r3skill- compute_capability_summary will raise ValueError
|
|
When r3skill- I invoke show "local/show-cap-err" in format "json"
|
|
Then r3skill- the CLI exit code should be 0
|
|
And r3skill- the output should be valid JSON
|
|
And r3skill- the JSON output key "capability_summary" should be null
|
|
|
|
# -------------------------------------------------------------------
|
|
# list rich format: long description truncation (lines 696-700)
|
|
# -------------------------------------------------------------------
|
|
|
|
Scenario: List in rich format truncates long descriptions
|
|
Given r3skill- a registered skill "local/long-desc" with a description longer than 50 chars
|
|
When r3skill- I invoke list in rich format
|
|
Then r3skill- the CLI exit code should be 0
|
|
And r3skill- the long description in the output should be truncated
|
|
|
|
# -------------------------------------------------------------------
|
|
# refresh: agent_skills_paths discovery (lines 953-980)
|
|
# -------------------------------------------------------------------
|
|
|
|
Scenario: Refresh single skill with agent_skills_paths discovery
|
|
Given r3skill- a registered skill "local/refresh-agent" with tool_refs
|
|
And r3skill- agent_skills_paths config resolves to a valid path with discovered skills
|
|
When r3skill- I invoke refresh "local/refresh-agent" in rich format
|
|
Then r3skill- the CLI exit code should be 0
|
|
And r3skill- the output should contain "Agent Skills"
|
|
And r3skill- the output should contain "Discovered"
|
|
|
|
Scenario: Refresh all skills with agent_skills_paths and discovery errors
|
|
Given r3skill- a registered skill "local/refresh-err" with tool_refs
|
|
And r3skill- agent_skills_paths config resolves with discovery errors
|
|
When r3skill- I invoke refresh --all in rich format
|
|
Then r3skill- the CLI exit code should be 0
|
|
And r3skill- the output should contain "Warning"
|
|
|
|
# -------------------------------------------------------------------
|
|
# refresh: single skill resolve_tools ValueError (lines 1017-1026, 1044-1046)
|
|
# -------------------------------------------------------------------
|
|
|
|
Scenario: Refresh single skill with ValueError during resolve_tools
|
|
Given r3skill- a registered skill "local/refresh-fail" with tool_refs
|
|
And r3skill- resolve_tools will raise ValueError for "local/refresh-fail"
|
|
When r3skill- I invoke refresh "local/refresh-fail" in rich format
|
|
Then r3skill- the CLI exit code should not be 0
|
|
And r3skill- the output should contain "Refresh failed"
|
|
|
|
# -------------------------------------------------------------------
|
|
# refresh: all skills with one skill ValueError (lines 1017-1026 in loop)
|
|
# -------------------------------------------------------------------
|
|
|
|
Scenario: Refresh all skills where one skill has resolve_tools ValueError
|
|
Given r3skill- a registered skill "local/good-skill" with tool_refs
|
|
And r3skill- a registered skill "local/bad-skill" with tool_refs
|
|
And r3skill- resolve_tools will raise ValueError for "local/bad-skill"
|
|
When r3skill- I invoke refresh --all in rich format
|
|
Then r3skill- the CLI exit code should be 0
|
|
And r3skill- the output should contain "Errors"
|
|
|
|
# -------------------------------------------------------------------
|
|
# refresh: non-rich format with mcp_errors (lines 1035-1036)
|
|
# -------------------------------------------------------------------
|
|
|
|
Scenario: Refresh all in JSON format with mcp errors
|
|
Given r3skill- a registered skill "local/ok-skill" with tool_refs
|
|
And r3skill- a registered skill "local/err-skill" with tool_refs
|
|
And r3skill- resolve_tools will raise ValueError for "local/err-skill"
|
|
When r3skill- I invoke refresh --all in format "json"
|
|
Then r3skill- the CLI exit code should be 0
|
|
And r3skill- the output should be valid JSON
|
|
And r3skill- the JSON output should have key "errors"
|
|
|
|
# -------------------------------------------------------------------
|
|
# refresh: general Exception catch (lines 1106-1108)
|
|
# -------------------------------------------------------------------
|
|
|
|
Scenario: Refresh raises unexpected Exception
|
|
Given r3skill- a registered skill "local/exc-skill" with tool_refs
|
|
And r3skill- list_skills will raise RuntimeError
|
|
When r3skill- I invoke refresh --all in rich format
|
|
Then r3skill- the CLI exit code should not be 0
|
|
And r3skill- the output should contain "Refresh error"
|
|
|
|
# -------------------------------------------------------------------
|
|
# refresh: agent_skills_paths empty path (lines 961-962 false branch)
|
|
# -------------------------------------------------------------------
|
|
|
|
Scenario: Refresh with empty agent_skills_paths skips discovery
|
|
Given r3skill- a registered skill "local/no-discovery" with tool_refs
|
|
And r3skill- agent_skills_paths config resolves to empty string
|
|
When r3skill- I invoke refresh "local/no-discovery" in rich format
|
|
Then r3skill- the CLI exit code should be 0
|
|
And r3skill- the output should not contain "Discovered"
|
|
|
|
# -------------------------------------------------------------------
|
|
# refresh: non-rich single skill (lines 1029-1037)
|
|
# -------------------------------------------------------------------
|
|
|
|
Scenario: Refresh single skill with JSON format returns structured output
|
|
Given r3skill- a registered skill "local/json-refresh" with tool_refs
|
|
When r3skill- I invoke refresh "local/json-refresh" in format "json"
|
|
Then r3skill- the CLI exit code should be 0
|
|
And r3skill- the output should be valid JSON
|
|
And r3skill- the JSON output should have key "refreshed"
|
|
|
|
# -------------------------------------------------------------------
|
|
# _print_skill_detail: both timestamps None (lines 253-254)
|
|
# -------------------------------------------------------------------
|
|
|
|
Scenario: Show skill in rich format with no timestamps shows unknown
|
|
Given r3skill- a registered skill "local/no-ts" with tool_refs
|
|
And r3skill- timestamps for "local/no-ts" are removed
|
|
When r3skill- I invoke show "local/no-ts" in rich format
|
|
Then r3skill- the CLI exit code should be 0
|
|
And r3skill- the output should contain "unknown"
|
|
|
|
# -------------------------------------------------------------------
|
|
# _print_skill_registered: include present AND registered (line 159 true)
|
|
# -------------------------------------------------------------------
|
|
|
|
Scenario: Add skill with includes where included skill IS registered
|
|
Given r3skill- a registered skill "local/base-inc" with tool_refs
|
|
And r3skill- a temp YAML for "local/parent-inc" that includes "local/base-inc"
|
|
When r3skill- I invoke add with the temp config in rich format
|
|
Then r3skill- the CLI exit code should be 0
|
|
And r3skill- the output should contain "registered"
|
|
And r3skill- the output should contain "Includes"
|
|
|
|
# -------------------------------------------------------------------
|
|
# _print_skill_update_changes: old_skill with includes/mcp changed
|
|
# -------------------------------------------------------------------
|
|
|
|
Scenario: Update skill changes includes and MCP servers shows diff
|
|
Given r3skill- a temp YAML for "local/upd-diff" with tool_refs and MCP
|
|
And r3skill- the skill "local/upd-diff" is pre-registered via add
|
|
And r3skill- a second temp YAML for "local/upd-diff" with different includes and MCP
|
|
When r3skill- I invoke add with the second config and --update in rich format
|
|
Then r3skill- the CLI exit code should be 0
|
|
And r3skill- the output should contain "Changes"
|
|
And r3skill- the output should contain "Includes Changed"
|
|
And r3skill- the output should contain "MCP Servers Changed"
|
|
|
|
# -------------------------------------------------------------------
|
|
# _print_skill_tools: inline tool with writes and checkpointable
|
|
# -------------------------------------------------------------------
|
|
|
|
Scenario: Tools command with inline tool having writes and checkpointable
|
|
Given r3skill- a registered skill "local/inline-caps" with inline tools having capabilities
|
|
When r3skill- I invoke tools "local/inline-caps" in rich format
|
|
Then r3skill- the CLI exit code should be 0
|
|
And r3skill- the output should contain "custom"
|
|
|
|
# -------------------------------------------------------------------
|
|
# remove: confirm prompt with yes (line 553 true branch via input)
|
|
# -------------------------------------------------------------------
|
|
|
|
Scenario: Remove skill without --yes and confirm with y
|
|
Given r3skill- a registered skill "local/confirm-rm" with tool_refs
|
|
When r3skill- I invoke remove "local/confirm-rm" without --yes and confirm
|
|
Then r3skill- the CLI exit code should be 0
|
|
And r3skill- the output should contain "Skill Removed"
|
|
|
|
# -------------------------------------------------------------------
|
|
# list non-rich: capability summary KeyError fallback
|
|
# -------------------------------------------------------------------
|
|
|
|
Scenario: List with JSON format falls back when capability summary raises KeyError
|
|
Given r3skill- a registered skill "local/key-err-list" with tool_refs
|
|
And r3skill- compute_capability_summary will raise KeyError
|
|
When r3skill- I invoke list in format "json"
|
|
Then r3skill- the CLI exit code should be 0
|
|
And r3skill- the output should be valid JSON
|
|
And r3skill- the JSON list first item "capability_summary" should be null
|
|
|
|
# -------------------------------------------------------------------
|
|
# show non-rich: capability summary KeyError fallback
|
|
# -------------------------------------------------------------------
|
|
|
|
Scenario: Show with JSON format falls back when capability summary raises KeyError
|
|
Given r3skill- a registered skill "local/key-err-show" with tool_refs
|
|
And r3skill- compute_capability_summary will raise KeyError
|
|
When r3skill- I invoke show "local/key-err-show" in format "json"
|
|
Then r3skill- the CLI exit code should be 0
|
|
And r3skill- the output should be valid JSON
|
|
And r3skill- the JSON output key "capability_summary" should be null
|