Feature: Edge case data variation — empty, null, boundary, special characters, invalid types
  As a CleverAgents developer
  I want edge case tests to cover empty/null values, boundary lengths, special characters,
  and invalid input types systematically
  So that the system handles all boundary conditions correctly

  # ─────────────────────────────────────────────────────────────────────────
  # New edge-case scenarios added as part of issue #2772.
  # These complement the Scenario Outline refactoring in the other
  # data_variation_*.feature files.
  # ─────────────────────────────────────────────────────────────────────────

  # ─────────────────────────────────────────────────────────────────────────
  # Python content sanitization — edge cases
  # ─────────────────────────────────────────────────────────────────────────

  Background:
    Given I have a plan service for sanitization tests

  Scenario Outline: Sanitize valid Python expressions of varying complexity
    When I sanitize the python content "<content>"
    Then the sanitized content should be "<content>"
    And the sanitization error should be None
    And the sanitization reason should be None

    Examples: Simple valid Python expressions
      | content                    | description                              |
      | x = 1 + 2                  | simple arithmetic assignment             |
      | result = "hello"           | string assignment                        |
      | items = []                 | empty list assignment                    |
      | data = {}                  | empty dict assignment                    |
      | flag = True                | boolean assignment                       |
      | value = None               | None assignment                          |
      | count = 0                  | zero assignment                          |

  Scenario Outline: Sanitize Python with markdown code fences strips fences
    When I sanitize the python content with code fences wrapping "<inner>"
    Then the sanitized content should be "<inner>"
    And the sanitization error should be None
    And the sanitization reason should be "code_fence_removed"

    Examples: Code fence variations
      | inner                      | description                              |
      | x = 42                     | simple assignment in fences              |
      | result = "hello"           | string assignment in fences              |
      | items = [1, 2, 3]          | list assignment in fences                |
      | def foo(): pass            | function definition in fences            |

  Scenario Outline: Sanitize non-Python prose wraps in docstring
    When I sanitize the python content "<prose>"
    Then the sanitization error should be None
    And the sanitization reason should be "docstring_wrapped"

    Examples: Non-Python prose inputs
      | prose                                          | description                              |
      | This is just plain English text, not code.     | plain English sentence                   |
      | Please implement the feature as described.     | instruction-style prose                  |
      | The function should return a list of items.    | description-style prose                  |

  Scenario: Sanitize content with null byte returns error
    When I sanitize python content containing a null byte
    Then the sanitization error should not be None

  # ─────────────────────────────────────────────────────────────────────────
  # Project name validation — edge cases with special characters
  # ─────────────────────────────────────────────────────────────────────────

  Scenario Outline: Project rejects names with various special characters
    When I try to create a project with name "<invalid_name>"
    Then a project validation error should be raised mentioning "alphanumeric"

    Examples: Special character edge cases
      | invalid_name           | description                              |
      | my@project             | at-sign                                  |
      | my/project             | forward slash                            |
      | project!               | exclamation mark                         |
      | proj#tag               | hash symbol                              |
      | proj%done              | percent sign                             |
      | proj^up                | caret                                    |
      | proj&more              | ampersand                                |
      | proj*star              | asterisk                                 |
      | proj+plus              | plus sign                                |
      | proj=eq                | equals sign                              |
      | proj<less              | less-than sign                           |
      | proj>more              | greater-than sign                        |
      | proj?q                 | question mark                            |
      | proj.pipe              | period character                         |
      | proj:colon             | colon                                    |
      | proj;semi              | semicolon                                |

  Scenario: Project rejects empty name
    When I try to create a project with empty name
    Then a project validation error should be raised

  Scenario Outline: Project accepts valid names with allowed characters
    When I create a project fixture with name "<valid_name>"
    Then the project should be created with that name

    Examples: Valid name formats
      | valid_name              | description                              |
      | simple                  | plain alphanumeric                       |
      | my-project              | hyphenated name                          |
      | my_project              | underscored name                         |
      | my project              | name with space                          |
      | project123              | name with trailing numbers               |
      | 123project              | name starting with numbers               |
      | a                       | single character                         |
      | My Project Name         | mixed case with spaces                   |

  # ─────────────────────────────────────────────────────────────────────────
  # NamespacedName — special character edge cases
  # ─────────────────────────────────────────────────────────────────────────

  Scenario Outline: NamespacedName rejects names with special characters in namespace
    When I parse the namespaced name "<full_name>" expecting an error
    Then a ValueError should be raised

    Examples: Special characters in namespace
      | full_name              | description                              |
      | bad@ns/name            | at-sign in namespace                     |
      | bad ns/name            | space in namespace                       |
      | bad!ns/name            | exclamation in namespace                 |
      | bad#ns/name            | hash in namespace                        |

  Scenario Outline: NamespacedName rejects names with special characters in name component
    When I parse the namespaced name "<full_name>" expecting an error
    Then a ValueError should be raised

    Examples: Special characters in name component
      | full_name              | description                              |
      | ns/bad name            | space in name component                  |
      | ns/bad@name            | at-sign in name component                |
      | ns/bad!name            | exclamation in name component            |
      | ns/bad#name            | hash in name component                   |
      | ns/bad/extra           | extra slash (three components)           |

  Scenario Outline: NamespacedName accepts names at various boundary lengths
    When I parse the namespaced name "<full_name>"
    Then the parsed namespace should be "<namespace>"
    And the parsed item name should be "<item_name>"

    Examples: Boundary length names
      | full_name                                 | namespace  | item_name                         | description                  |
      | a/b                                       | a          | b                                 | minimum length (1 char each) |
      | ab/cd                                     | ab         | cd                                | two chars each               |
      | abc/def                                   | abc        | def                               | three chars each             |
      | local/my-tool                             | local      | my-tool                           | standard short name          |
      | my-namespace/my-tool-name                 | my-namespace | my-tool-name                    | medium length names          |

  # ─────────────────────────────────────────────────────────────────────────
  # ULID validation — boundary and special character edge cases
  # ─────────────────────────────────────────────────────────────────────────

  Scenario Outline: ULID validation rejects inputs at boundary lengths
    When I call _validate_plan_ulid with "<input>"
    Then ulid-val the validation should raise ValidationError
    And ulid-val the error message should contain "ULID"

    Examples: Boundary length inputs
      | input                       | description                              |
      | 01ARZ3NDEKTSV4RRFFQ69G5FA   | 25 chars (one short of valid)            |
      | 01ARZ3NDEKTSV4RRFFQ69G5FAVX | 27 chars (one over valid)                |
      | A                           | single character                         |
      | 01ARZ3NDEK                  | 10 chars (too short)                     |

  Scenario Outline: ULID validation accepts valid ULIDs at boundary values
    When I call _validate_plan_ulid with "<ulid>"
    Then ulid-val the validation should succeed and return "<ulid>"

    Examples: Valid ULIDs at boundary values
      | ulid                       | description                              |
      | 00000000000000000000000000 | all zeros (minimum value)                |
      | 7ZZZZZZZZZZZZZZZZZZZZZZZZZ | all max chars (maximum value)            |
      | 01HXM8C2ZK4Q7C2B3F2R4VYV6J | standard valid ULID                      |

  Scenario Outline: ULID validation rejects ULIDs with illegal characters
    When I call _validate_plan_ulid with "<input>"
    Then ulid-val the validation should raise ValidationError
    And ulid-val the error message should contain "ULID"

    Examples: Crockford base32 excluded characters
      | input                       | description                              |
      | 01ARZ3NDEKTSV4RRFFQ69G5FII  | contains I (excluded from base32)        |
      | 01ARZ3NDEKTSV4RRFFQ69G5FLL  | contains L (excluded from base32)        |
      | 01ARZ3NDEKTSV4RRFFQ69G5FOO  | contains O (excluded from base32)        |
      | 01ARZ3NDEKTSV4RRFFQ69G5FUU  | contains U (excluded from base32)        |
      | 01ARZ3NDEKTSV4RRFFQ69G5F!@  | contains special characters              |
      | 01ARZ3NDEKTSV4RRFFQ69G5F-X  | contains hyphen                          |
      | 01ARZ3NDEKTSV4RRFFQ69G5F.X  | contains period                          |

  # ─────────────────────────────────────────────────────────────────────────
  # Skill schema — edge cases for inline tool source values
  # ─────────────────────────────────────────────────────────────────────────

  Scenario Outline: Skill schema rejects invalid inline tool source values
    Given a skill YAML string with an inline tool source "<source>"
    When I validate the skill schema expecting failure
    Then the skill schema validation should fail
    And the skill schema error should mention "custom"

    Examples: Invalid source values
      | source    | description                              |
      | plugin    | plugin source (not supported)            |
      | external  | external source (not supported)          |
      | remote    | remote source (not supported)            |
      | builtin   | builtin source (not supported)           |
      | inline    | inline source (not supported)            |
      | file      | file source (not supported)              |

  # ─────────────────────────────────────────────────────────────────────────
  # Skill schema — edge cases for MCP transport values
  # ─────────────────────────────────────────────────────────────────────────

  Scenario Outline: Skill schema rejects invalid MCP transport values
    Given a skill YAML string with MCP transport "<transport>"
    When I validate the skill schema expecting failure
    Then the skill schema validation should fail
    And the skill schema error should mention "transport"

    Examples: Invalid transport values
      | transport   | description                              |
      | grpc        | gRPC (not supported)                     |
      | websocket   | WebSocket (not supported)                |
      | http        | plain HTTP (not supported)               |
      | tcp         | TCP (not supported)                      |
      | invalid     | completely invalid value                 |
      | ftp         | FTP (not supported)                      |
      | amqp        | AMQP (not supported)                     |
