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
