Feature: Validation test fixtures
  As a QA engineer
  I want to validate that code sanitization, model validation, and input coercion handle edge cases
  So that edge case project structures and malformed input data are properly rejected

  # NOTE: Sections 1, 1b, 2, and 2b (AST security validation, RestrictedPython,
  # Lambda AST validation) were removed as part of SEC1.  eval()/exec() are no
  # longer used in stream_router.py; the SEC1 approach uses named operation and
  # transform registries instead.  See features/security_eval.feature for the
  # replacement tests.

  # ──────────────────────────────────────────────────
  # Section 3: Invalid code samples - Python content sanitization
  # ──────────────────────────────────────────────────

  Scenario: Sanitize valid Python passes through unchanged
    Given I have a plan service for sanitization tests
    When I sanitize the python content "x = 1 + 2"
    Then the sanitized content should be "x = 1 + 2"
    And the sanitization error should be None
    And the sanitization reason should be None

  Scenario: Sanitize Python with markdown code fences
    Given I have a plan service for sanitization tests
    When I sanitize the python content with code fences wrapping "x = 42"
    Then the sanitized content should be "x = 42"
    And the sanitization error should be None
    And the sanitization reason should be "code_fence_removed"

  Scenario: Sanitize non-Python prose falls back to docstring wrapping
    Given I have a plan service for sanitization tests
    When I sanitize the python content "This is just plain English text, not code."
    Then the sanitization error should be None
    And the sanitization reason should be "docstring_wrapped"

  Scenario: Sanitize irrecoverable syntax returns error
    Given I have a plan service for sanitization tests
    When I sanitize python content containing a null byte
    Then the sanitization error should not be None

  # ──────────────────────────────────────────────────
  # Section 4: Edge case project structures - Project model validation
  # ──────────────────────────────────────────────────

  Scenario: Project rejects name with special characters
    When I try to create a project with name "my@project"
    Then a project validation error should be raised mentioning "alphanumeric"

  Scenario: Project rejects name with slashes
    When I try to create a project with name "my/project"
    Then a project validation error should be raised mentioning "alphanumeric"

  Scenario: Project rejects name with exclamation
    When I try to create a project with name "project!"
    Then a project validation error should be raised mentioning "alphanumeric"

  Scenario: Project accepts name with hyphens underscores and spaces
    When I create a project fixture with name "my-project_v2 final"
    Then the project should be created with that name

  Scenario: Project resolves relative path to absolute
    When I create a project with relative path "relative/path"
    Then the project fixture path should be absolute

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

  # ──────────────────────────────────────────────────
  # Section 5: Malformed input data - Change list coercion
  # ──────────────────────────────────────────────────

  Scenario: Coerce empty change list returns empty list
    Given I have a plan service for coercion tests
    When I coerce an empty change list
    Then the coerced result should be an empty list

  Scenario: Coerce mixed dict and Change entries
    Given I have a plan service for coercion tests
    When I coerce a list with one dict entry and one Change entry
    Then the coerced result should have 2 changes

  Scenario: Coerce non-list input raises PlanError
    Given I have a plan service for coercion tests
    When I try to coerce a non-list input
    Then a PlanError should be raised mentioning "invalid change payload"

  Scenario: Coerce list with non-change non-dict entry raises PlanError
    Given I have a plan service for coercion tests
    When I try to coerce a list containing an integer
    Then a PlanError should be raised mentioning "non-change entry"

  # ──────────────────────────────────────────────────
  # Section 6: Malformed input data - ActionArgument parsing
  # ──────────────────────────────────────────────────

  Scenario: Parse argument with too few parts
    When I try to parse action argument fixture "onlyname"
    Then an argument fixture parse error should be raised

  Scenario: Parse argument with invalid type
    When I try to parse action argument fixture "name:badtype:required:desc"
    Then an argument fixture parse error should be raised

  Scenario: Parse argument with invalid requirement
    When I try to parse action argument fixture "name:str:sometimes:desc"
    Then an argument fixture parse error should be raised

  Scenario: Parse argument with reserved keyword name
    When I try to create argument with name "class"
    Then the argument name should be accepted as valid identifier
