Files
cleveragents-core/features/skill_cli_coverage_r3.feature
freemo c9abb45adf
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 15s
CI / build (pull_request) Successful in 16s
CI / quality (pull_request) Successful in 18s
CI / security (pull_request) Successful in 31s
CI / typecheck (pull_request) Successful in 55s
CI / integration_tests (pull_request) Successful in 3m28s
CI / unit_tests (pull_request) Successful in 10m38s
CI / docker (pull_request) Successful in 16s
CI / benchmark-regression (pull_request) Successful in 20m39s
CI / coverage (pull_request) Successful in 41m22s
CI / lint (push) Successful in 13s
CI / quality (push) Successful in 17s
CI / build (push) Successful in 22s
CI / typecheck (push) Successful in 29s
CI / security (push) Successful in 29s
CI / benchmark-regression (push) Has been skipped
CI / integration_tests (push) Successful in 2m40s
CI / unit_tests (push) Successful in 11m4s
CI / docker (push) Successful in 1m5s
CI / benchmark-publish (push) Successful in 12m10s
CI / coverage (push) Successful in 1h7m46s
test(coverage): add Behave BDD scenarios for 9 under-covered modules
Added 246 new BDD scenarios across 9 feature files to improve unit test
coverage for modules that were either entirely untested or had significant
coverage gaps:

- lock_service_coverage.feature (27 scenarios): validation branches,
  TTL boundaries, re-entrant acquisition, rollback on exceptions
- plan_apply_service_coverage.feature (54 scenarios): operation labels,
  diff rendering (plain/rich/json), artifact building, validation gate,
  changeset resolution and cleanup
- plan_executor_coverage.feature (51 scenarios): step parsing, execute
  actor integration, strategize/execute guards, stub retry/recovery,
  decision tree construction
- skill_cli_coverage_r3.feature (22 scenarios): tools refresh, list/show
  JSON fallback, capability summary errors, remove confirmation
- changeset_repository_coverage.feature (39 scenarios): entry/tool repos
  validation, database error wrapping, domain conversion, SQLite store
  CRUD operations
- repositories_coverage.feature (20 scenarios): get_by_name/namespace
  errors, list_available filters, delete with ActionInUseError, plan
  update with invariants/processing_state/error_details
- sandbox_copy_on_write_coverage.feature (12 scenarios): create OSError
  wrapping, get_path state transitions, commit edge cases, rollback
  errors, cleanup with missing paths
- bridge_coverage.feature (8 scenarios): __del__ suppression, async task
  cancellation, execute_graph message type handling, stream config,
  state checkpointer
- plan_cli_coverage.feature (13 scenarios): legacy apply/list/cd paths,
  use-action with estimation/invariant actors, lifecycle-apply guards,
  status errors, error recovery display

All 246 scenarios (1105 steps) pass. Step definitions use unique prefixes
to prevent ambiguous step conflicts with existing tests.

ISSUES CLOSED: #467
2026-02-27 13:47:42 -05:00

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