Feature: NamespacedName validation data variation — Scenario Outline refactoring
  As a CleverAgents developer
  I want NamespacedName validation tests to cover a wide range of inputs
  So that edge cases and boundary conditions are systematically exercised

  # ─────────────────────────────────────────────────────────────────────────
  # Refactored from plan_namespaced_name_validation.feature using Scenario
  # Outline.  Each Examples table row exercises a distinct code path.
  # ─────────────────────────────────────────────────────────────────────────

  # ─────────────────────────────────────────────────────────────────────────
  # Valid namespaced names — all should parse successfully
  # ─────────────────────────────────────────────────────────────────────────

  Scenario Outline: NamespacedName.parse() accepts valid namespaced names
    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: Standard valid names
      | full_name              | namespace | item_name       | description                        |
      | abc123/my-action       | abc123    | my-action       | namespace starts with letter       |
      | local/a123-action      | local     | a123-action     | name starts with letter            |
      | my-org/my-action       | my-org    | my-action       | kebab-case namespace and name      |
      | x/y                    | x         | y               | single-char namespace and name     |
      | org/tool-v2            | org       | tool-v2         | name with version suffix           |
      | builtin/read-file      | builtin   | read-file       | builtin namespace                  |
      | local/my-skill         | local     | my-skill        | local namespace                    |

    Examples: Names with numbers (not at start)
      | full_name              | namespace | item_name       | description                        |
      | org123/tool456         | org123    | tool456         | numbers in middle of both parts    |
      | a1b2c3/d4e5f6          | a1b2c3    | d4e5f6          | alternating letters and numbers    |
      | ns/name-with-123       | ns        | name-with-123   | numbers at end of 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             |
      | my-namespace/my-tool-name                 | my-namespace | my-tool-name               | medium length names          |

  # ─────────────────────────────────────────────────────────────────────────
  # Invalid namespaced names — special characters in namespace
  # ─────────────────────────────────────────────────────────────────────────

  Scenario Outline: NamespacedName.parse() rejects namespace with special characters
    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                        |

  # ─────────────────────────────────────────────────────────────────────────
  # Invalid namespaced names — special characters in name component
  # ─────────────────────────────────────────────────────────────────────────

  Scenario Outline: NamespacedName.parse() rejects name component with special characters
    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)           |

  # ─────────────────────────────────────────────────────────────────────────
  # Invalid namespaced names — via constructor
  # ─────────────────────────────────────────────────────────────────────────

  Scenario Outline: NamespacedName constructor rejects invalid namespace formats
    When I construct a NamespacedName with namespace "<namespace>" and name "<name>" expecting an error
    Then a ValueError should be raised

    Examples: Invalid namespace formats
      | namespace | name       | description                              |
      | bad@ns    | valid-name | at-sign in namespace                     |
      | bad ns    | valid-name | space in namespace                       |
      | bad!ns    | valid-name | exclamation in namespace                 |
      | bad#ns    | valid-name | hash in namespace                        |

  Scenario Outline: NamespacedName constructor rejects invalid name formats
    When I construct a NamespacedName with namespace "<namespace>" and name "<name>" expecting an error
    Then a ValueError should be raised

    Examples: Invalid name formats
      | namespace | name          | description                              |
      | local     | bad name      | space in name                            |
      | local     | bad@name      | at-sign in name                          |
      | local     | bad!name      | exclamation in name                      |
      | local     | bad#name      | hash in name                             |
      | local     | bad/name      | slash in name                            |
