Feature: Skill Search and Directory Tools As a developer I want skill-level directory listing and search tools So that agents can list directories, match files by glob, and search file contents with regex # ---- ListDir ---- Scenario: ListDir lists directory contents Given a skill search sandbox directory And a search sandbox file "a.txt" with content "a" And a search sandbox file "b.py" with content "b" When I list-dir "." in the search sandbox Then the search tool result should be successful And the search output "total" should be greater than or equal to 2 And the search output "truncated" should be boolean false Scenario: ListDir with type filter for files only Given a skill search sandbox directory And a search sandbox file "file.txt" with content "content" And a search sandbox subdirectory "subdir" When I list-dir-typed "." with type_filter "files" Then the search tool result should be successful And all search entries should not be directories Scenario: ListDir with type filter for dirs only Given a skill search sandbox directory And a search sandbox file "file.txt" with content "content" And a search sandbox subdirectory "subdir" When I list-dir-typed "." with type_filter "dirs" Then the search tool result should be successful And all search entries should be directories Scenario: ListDir with ignore patterns Given a skill search sandbox directory And a search sandbox file "keep.txt" with content "keep" And a search sandbox file "ignore.log" with content "ignore" When I list-dir-ignoring "." ignoring "*.log" Then the search tool result should be successful And no search entry should have name "ignore.log" Scenario: ListDir with size limit Given a skill search sandbox directory And a search sandbox file "1.txt" with content "one" And a search sandbox file "2.txt" with content "two" And a search sandbox file "3.txt" with content "three" When I list-dir-limited "." with limit 2 Then the search tool result should be successful And the search output "truncated" should be boolean true And the search output "total" should equal 2 Scenario: ListDir on non-directory raises error Given a skill search sandbox directory And a search sandbox file "notadir.txt" with content "x" When I list-dir "notadir.txt" in the search sandbox Then the search tool result should not be successful And the search tool error should mention "not a directory" Scenario: ListDir with invalid type_filter raises error Given a skill search sandbox directory When I list-dir-typed "." with type_filter "invalid" Then the search tool result should not be successful And the search tool error should mention "Invalid type_filter" # ---- Glob ---- Scenario: Glob matches files by pattern Given a skill search sandbox directory And a search sandbox file "main.py" with content "code" And a search sandbox file "test.py" with content "test" And a search sandbox file "readme.md" with content "docs" When I glob-match "." for "*.py" Then the search tool result should be successful And the search glob total should be 2 Scenario: Glob with exclude patterns Given a skill search sandbox directory And a search sandbox file "main.py" with content "code" And a search sandbox file "test.py" with content "test" When I glob-exclude "." for "*.py" excluding "test*" Then the search tool result should be successful And the search glob total should be 1 And no search match should have name "test.py" Scenario: Glob with include filter Given a skill search sandbox directory And a search sandbox file "main.py" with content "code" And a search sandbox file "test.py" with content "test" When I glob-include "." for "*" including "*.py" Then the search tool result should be successful And the search glob total should be at least 2 Scenario: Glob returns deterministic sorted results Given a skill search sandbox directory And a search sandbox file "c.txt" with content "c" And a search sandbox file "a.txt" with content "a" And a search sandbox file "b.txt" with content "b" When I glob-match "." for "*.txt" Then the search tool result should be successful And the search glob results should be sorted by name Scenario: Glob on non-directory raises error Given a skill search sandbox directory And a search sandbox file "notadir.txt" with content "x" When I glob-match "notadir.txt" for "*.txt" Then the search tool result should not be successful And the search tool error should mention "not a directory" Scenario: Glob with limit truncation Given a skill search sandbox directory And a search sandbox file "1.txt" with content "one" And a search sandbox file "2.txt" with content "two" And a search sandbox file "3.txt" with content "three" When I glob-limited "." for "*.txt" with limit 2 Then the search tool result should be successful And the search output "truncated" should be boolean true # ---- Grep ---- Scenario: Grep finds matching lines Given a skill search sandbox directory And a search sandbox file "haystack.txt" with content "needle in a haystack" When I grep-search "." for "needle" Then the search tool result should be successful And the search grep total should be at least 1 Scenario: Grep with context lines Given a skill search sandbox directory And a search sandbox file "context.txt" with lines "before,match,after" When I grep-context "." for "match" with context 1 Then the search tool result should be successful And the search grep first match should have context_before And the search grep first match should have context_after Scenario: Grep skips binary files Given a skill search sandbox directory And a search sandbox binary file "data.bin" And a search sandbox file "text.txt" with content "findme" When I grep-search "." for "findme" Then the search tool result should be successful And the search grep matches should not reference "data.bin" Scenario: Grep with per-file match cap Given a skill search sandbox directory And a search sandbox file "many.txt" with lines "match,match,match,match,match" When I grep-capped "." for "match" with per_file_cap 2 Then the search tool result should be successful And the search grep total should equal 2 Scenario: Grep with total match limit Given a skill search sandbox directory And a search sandbox file "m1.txt" with lines "hit,hit,hit" And a search sandbox file "m2.txt" with lines "hit,hit,hit" When I grep-maxed "." for "hit" with max_matches 3 Then the search tool result should be successful And the search grep total should equal 3 And the search output "truncated" should be boolean true Scenario: Grep with invalid regex raises error Given a skill search sandbox directory When I grep-search "." for "[invalid" Then the search tool result should not be successful And the search tool error should mention "Invalid regex" Scenario: Grep on non-directory raises error Given a skill search sandbox directory And a search sandbox file "notadir.txt" with content "x" When I grep-search "notadir.txt" for "x" Then the search tool result should not be successful And the search tool error should mention "not a directory" # ---- Path Traversal ---- Scenario: Path traversal in list-dir is rejected Given a skill search sandbox directory When I list-dir "../../etc" in the search sandbox Then the search tool result should not be successful And the search tool error should mention "traversal" Scenario: Path traversal in glob is rejected Given a skill search sandbox directory When I glob-match "../../etc" for "*" Then the search tool result should not be successful And the search tool error should mention "traversal" Scenario: Path traversal in grep is rejected Given a skill search sandbox directory When I grep-search "../../etc" for "root" Then the search tool result should not be successful And the search tool error should mention "traversal" # ---- Read-Only Capability ---- Scenario: ListDir has read_only capability Given a skill search tools registry Then the search tool "skill/list-dir" should have read_only capability Scenario: Glob has read_only capability Given a skill search tools registry Then the search tool "skill/glob" should have read_only capability Scenario: Grep has read_only capability Given a skill search tools registry Then the search tool "skill/grep" should have read_only capability # ---- Registration ---- Scenario: Register all skill search tools Given a skill search tools registry Then the search registry should contain 3 tools And the search registry should contain tool "skill/list-dir" And the search registry should contain tool "skill/glob" And the search registry should contain tool "skill/grep" # ---- Coverage: OSError fallbacks, include patterns, directory skip ---- Scenario: ListDir handles stat failure gracefully Given a skill search sandbox directory And a search sandbox file "statfail.txt" with content "test" When I execute list-dir with a stat failure mock Then the list-dir result should contain "statfail.txt" with size 0 Scenario: Glob filters by include pattern Given a skill search sandbox directory And a search sandbox file "keep.txt" with content "a" And a search sandbox file "skip.py" with content "b" When I execute glob with pattern "*" and include "*.txt" Then the glob results should contain "keep.txt" And the glob results should not contain "skip.py" Scenario: Glob handles stat failure gracefully Given a skill search sandbox directory And a search sandbox file "globstat.txt" with content "test" When I execute glob with a stat failure mock and pattern "*.txt" Then the glob result should contain "globstat.txt" with size 0 Scenario: Grep skips directories in rglob Given a skill search sandbox directory And a search sandbox subdirectory "subdir" And a search sandbox file "subdir/match.txt" with content "findme here" When I execute grep with pattern "findme" and include "*" Then the grep results should contain "match.txt" And the grep results should not contain a directory entry Scenario: Grep skips unreadable files gracefully Given a skill search sandbox directory And a search sandbox file "unreadable.txt" with content "content" When I execute grep with a read_text failure mock and pattern "content" Then the grep result should be empty