Files
cleveragents-core/features/skill_file_ops.feature
freemo 2980b14e7b test: boost combined branch coverage to 97% with additional behave scenarios
Add ~60 new behave scenarios across output rendering, tool router, file ops,
and skill search features targeting uncovered lines and branches. Key additions:
- ElementHandle validation guards (empty id, type, negative index, None args)
- Handle close/context-manager edge cases
- Table list-row and batch-row coverage
- Color/box-draw/JSON/YAML materializer edge cases
- Format selection paths (detect capabilities, explicit flag, empty format)
- Session ColumnDef, double-close guard, force-close open handles
- Tool router schema export and provider format scenarios
- File ops edge cases and search stat-failure/glob-include tests

All nox checks pass: lint, typecheck (0 errors), unit_tests (4730 scenarios),
coverage_report (97.0% >= 97% threshold).
2026-02-21 10:23:33 -05:00

278 lines
12 KiB
Gherkin

Feature: Skill File Operation Tools
As a developer
I want skill-level file operation tools
So that agents can safely read, write, edit, and delete files with
enhanced safety features like binary detection, atomic writes, and
newline normalization
# ---- ReadFile ----
Scenario: ReadFile reads text file content
Given a skill file ops sandbox directory
And a sandbox file "greeting.txt" with content "Hello, World!"
When I execute the "skill/file-read" tool with path "greeting.txt"
Then the skill tool result should be successful
And the skill output "content" should be "Hello, World!"
And the skill output "encoding" should be "utf-8"
And the skill output "size" should be greater than 0
Scenario: ReadFile with offset and limit
Given a skill file ops sandbox directory
And a sandbox file "lines.txt" with lines "line1,line2,line3,line4"
When I execute the "skill/file-read" tool with path "lines.txt" offset 1 limit 2
Then the skill tool result should be successful
And the skill output "content" should contain "line2"
And the skill output "content" should contain "line3"
And the skill output "content" should not contain "line1"
Scenario: ReadFile detects binary files and returns error
Given a skill file ops sandbox directory
And a binary file "image.png" in the sandbox
When I execute the "skill/file-read" tool with path "image.png"
Then the skill tool result should not be successful
And the skill tool error should mention "Binary file detected"
Scenario: ReadFile rejects missing file
Given a skill file ops sandbox directory
When I execute the "skill/file-read" tool with path "ghost.txt"
Then the skill tool result should not be successful
And the skill tool error should mention "not found"
Scenario: ReadFile enforces content size limit
Given a skill file ops sandbox directory
And an oversized file "huge.txt" in the sandbox
When I execute the "skill/file-read" tool with path "huge.txt"
Then the skill tool result should not be successful
And the skill tool error should mention "too large"
Scenario: ReadFile normalizes UTF-8 encoding
Given a skill file ops sandbox directory
And a sandbox file "utf8.txt" with content "caf\u00e9"
When I execute the "skill/file-read" tool with path "utf8.txt"
Then the skill tool result should be successful
And the skill output "content" should contain "caf"
Scenario: ReadFile rejects non-file path
Given a skill file ops sandbox directory
And a sandbox subdirectory "mydir"
When I execute the "skill/file-read" tool with path "mydir"
Then the skill tool result should not be successful
And the skill tool error should mention "Not a regular file"
# ---- WriteFile ----
Scenario: WriteFile creates a new file atomically
Given a skill file ops sandbox directory
When I execute the "skill/file-write" tool with path "new.txt" and content "created"
Then the skill tool result should be successful
And the skill output "created" should be boolean true
And the skill output "size" should be greater than 0
And the sandbox file "new.txt" should exist
Scenario: WriteFile overwrites an existing file
Given a skill file ops sandbox directory
And a sandbox file "existing.txt" with content "old"
When I execute the "skill/file-write" tool with path "existing.txt" and content "new"
Then the skill tool result should be successful
And the skill output "created" should be boolean false
Scenario: WriteFile creates parent directories
Given a skill file ops sandbox directory
When I execute the "skill/file-write" tool with path "sub/dir/file.txt" and content "nested"
Then the skill tool result should be successful
And the sandbox file "sub/dir/file.txt" should exist
Scenario: WriteFile with LF newline normalization
Given a skill file ops sandbox directory
When I write "skill/file-write" with path "lf.txt" content "a\r\nb\r\n" and newline_mode "lf"
Then the skill tool result should be successful
And the sandbox file "lf.txt" should not contain carriage return
Scenario: WriteFile with CRLF newline normalization
Given a skill file ops sandbox directory
When I write "skill/file-write" with path "crlf.txt" content "a\nb\n" and newline_mode "crlf"
Then the skill tool result should be successful
And the sandbox file "crlf.txt" should contain carriage return
# ---- EditFile ----
Scenario: EditFile with single replacement
Given a skill file ops sandbox directory
And a sandbox file "edit.txt" with content "foo bar foo"
When I execute the "skill/file-edit" tool replacing "foo" with "baz" in "edit.txt"
Then the skill tool result should be successful
And the skill output "replacements" should equal 1
Scenario: EditFile with replace_all
Given a skill file ops sandbox directory
And a sandbox file "edit.txt" with content "foo bar foo"
When I execute the "skill/file-edit" tool replacing all "foo" with "baz" in "edit.txt"
Then the skill tool result should be successful
And the skill output "replacements" should equal 2
Scenario: EditFile preserves file permissions
Given a skill file ops sandbox directory
And a sandbox file "perm.txt" with content "original" and mode 0o755
When I execute the "skill/file-edit" tool replacing "original" with "modified" in "perm.txt"
Then the skill tool result should be successful
And the sandbox file "perm.txt" should have mode 0o755
Scenario: EditFile with text not found raises error
Given a skill file ops sandbox directory
And a sandbox file "edit.txt" with content "foo bar"
When I execute the "skill/file-edit" tool replacing "notfound" with "x" in "edit.txt"
Then the skill tool result should not be successful
And the skill tool error should mention "not found"
Scenario: EditFile rejects missing file
Given a skill file ops sandbox directory
When I execute the "skill/file-edit" tool replacing "a" with "b" in "ghost.txt"
Then the skill tool result should not be successful
And the skill tool error should mention "not found"
# ---- DeleteFile ----
Scenario: DeleteFile removes an existing file
Given a skill file ops sandbox directory
And a sandbox file "doomed.txt" with content "goodbye"
When I execute the "skill/file-delete" tool with path "doomed.txt"
Then the skill tool result should be successful
And the skill output "existed" should be boolean true
And the sandbox file "doomed.txt" should not exist
Scenario: DeleteFile on nonexistent file reports not existed
Given a skill file ops sandbox directory
When I execute the "skill/file-delete" tool with path "ghost.txt"
Then the skill tool result should be successful
And the skill output "existed" should be boolean false
Scenario: DeleteFile rejects directory targets
Given a skill file ops sandbox directory
And a sandbox subdirectory "mydir"
When I execute the "skill/file-delete" tool with path "mydir"
Then the skill tool result should not be successful
And the skill tool error should mention "non-file"
# ---- Path Traversal Guards ----
Scenario: Path traversal with dotdot in read is rejected
Given a skill file ops sandbox directory
When I execute the "skill/file-read" tool with path "../../etc/passwd"
Then the skill tool result should not be successful
And the skill tool error should mention "traversal"
And the skill tool error should mention "../../etc/passwd"
Scenario: Path traversal in write is rejected
Given a skill file ops sandbox directory
When I execute the "skill/file-write" tool with path "../escape.txt" and content "evil"
Then the skill tool result should not be successful
And the skill tool error should mention "traversal"
And the skill tool error should mention "../escape.txt"
Scenario: Path traversal in edit is rejected
Given a skill file ops sandbox directory
And a sandbox file "safe.txt" with content "safe"
When I execute the "skill/file-edit" tool replacing "safe" with "x" in "../evil.txt"
Then the skill tool result should not be successful
And the skill tool error should mention "traversal"
Scenario: Path traversal in delete is rejected
Given a skill file ops sandbox directory
When I execute the "skill/file-delete" tool with path "../../etc/important"
Then the skill tool result should not be successful
And the skill tool error should mention "traversal"
# ---- Read-Only Enforcement ----
Scenario: ReadFile tool has read_only capability
Given a skill file tools registry
Then the "skill/file-read" tool should have read_only capability
Scenario: WriteFile tool has writes capability
Given a skill file tools registry
Then the "skill/file-write" tool should have writes capability
Scenario: EditFile tool has writes capability
Given a skill file tools registry
Then the "skill/file-edit" tool should have writes capability
Scenario: DeleteFile tool has writes capability
Given a skill file tools registry
Then the "skill/file-delete" tool should have writes capability
# ---- Registration ----
Scenario: Register all skill file tools
Given a skill file tools registry
Then the skill registry should contain 4 tools
And the skill registry should contain tool "skill/file-read"
And the skill registry should contain tool "skill/file-write"
And the skill registry should contain tool "skill/file-edit"
And the skill registry should contain tool "skill/file-delete"
# ---- Newline normalization helpers ----
Scenario: Newline normalization with invalid mode raises error
Given a skill file ops sandbox directory
When I write "skill/file-write" with path "bad.txt" content "test" and newline_mode "invalid"
Then the skill tool result should not be successful
And the skill tool error should mention "Invalid newline mode"
# ---- Empty path validation ----
Scenario: Empty path is rejected in read
Given a skill file ops sandbox directory
When I execute the "skill/file-read" tool with an empty path
Then the skill tool result should not be successful
And the skill tool error should mention "must not be empty"
# ---- Binary detection heuristic ----
Scenario: ReadFile detects ELF binary
Given a skill file ops sandbox directory
And an ELF binary file "program" in the sandbox
When I execute the "skill/file-read" tool with path "program"
Then the skill tool result should not be successful
And the skill tool error should mention "Binary file detected"
Scenario: ReadFile detects high control character content
Given a skill file ops sandbox directory
And a control-heavy file "binary.dat" in the sandbox
When I execute the "skill/file-read" tool with path "binary.dat"
Then the skill tool result should not be successful
And the skill tool error should mention "Binary file detected"
# ---- Coverage: _is_binary OSError, create_dirs, atomic write cleanup ----
Scenario: _is_binary returns false for unreadable path
Given a skill file ops sandbox directory
When I check _is_binary on a nonexistent path
Then _is_binary should return false
Scenario: WriteFile creates parent directories with create_dirs
Given a skill file ops sandbox directory
When I execute write_file with create_dirs to "deep/nested/dir/file.txt" and content "hello dirs"
Then the skill tool result should be successful
And the written file "deep/nested/dir/file.txt" should contain "hello dirs"
Scenario: _is_fd_closed returns false for open descriptor
When I check _is_fd_closed with an open file descriptor
Then _is_fd_closed should return false
Scenario: _is_fd_closed returns true for closed descriptor
When I check _is_fd_closed with a closed file descriptor
Then _is_fd_closed should return true
Scenario: WriteFile atomic write cleanup on os.replace failure
Given a skill file ops sandbox directory
When I simulate atomic write failure during replace
Then the temporary file should be cleaned up
And the original exception should propagate
Scenario: EditFile atomic write cleanup on os.chmod failure
Given a skill file ops sandbox directory
And a sandbox file "editable.txt" with content "original content"
When I simulate edit atomic write failure during chmod
Then the temporary file should be cleaned up after edit
And the original edit exception should propagate