Feature: Actor add CLI validates v3 YAML via ActorConfigSchema
  As a CleverAgents v3 user
  I want `agents actor add --config` to validate v3 YAML files using ActorConfigSchema
  So that invalid v3 actor definitions (cycles, missing fields, etc.) are rejected at registration time

  Background:
    Given an actor CLI runner
    And a temporary directory for test actor configs

  # ────────────────────────────────────────────────────────────
  # Valid v3 Actor Registration
  # ────────────────────────────────────────────────────────────

  Scenario: Register a valid v3 LLM actor via CLI
    Given a v3 LLM actor YAML file with name "local/test-llm"
    When I run the actor add command for "local/test-llm" with the prepared config file
    Then v3actor the command should succeed
    And the actor should be registered with type "llm"

  Scenario: Register a valid v3 TOOL actor via CLI
    Given a v3 TOOL actor YAML file with name "local/test-tool"
    When I run the actor add command for "local/test-tool" with the prepared config file
    Then v3actor the command should succeed
    And the actor should be registered with type "tool"

  Scenario: Register a valid v3 GRAPH actor via CLI
    Given a v3 GRAPH actor YAML file with name "local/test-graph"
    When I run the actor add command for "local/test-graph" with the prepared config file
    Then v3actor the command should succeed
    And the actor should be registered with type "graph"

  # ────────────────────────────────────────────────────────────
  # v3 Schema Validation Failures
  # ────────────────────────────────────────────────────────────

  # NOTE: Only "cycle" is checked here (not specific node names like "node_a"
  # or "node_b") because detect_cycles() only appends the single back-edge
  # node, not the full cycle path. Node names appear in the error incidentally
  # via Pydantic's input dump; checking them would couple the test to Pydantic's
  # internal error formatting which may change across versions.
  Scenario: Reject v3 GRAPH actor with cycle in route
    Given a v3 GRAPH actor YAML file with a cycle in the route
    When I run the actor add command for "local/broken-graph" with the prepared config file
    Then v3actor the command should fail
    And v3actor the error message should contain "cycle"

  Scenario: Reject v3 LLM actor without model field
    Given a v3 LLM actor YAML file without the model field
    When I run the actor add command for "local/no-model-llm" with the prepared config file
    Then v3actor the command should fail
    And v3actor the error message should contain "LLM actors require 'model' field"

  Scenario: Reject v3 TOOL actor without tools field
    Given a v3 TOOL actor YAML file without the tools field
    When I run the actor add command for "local/no-tools-tool" with the prepared config file
    Then v3actor the command should fail
    And v3actor the error message should contain "TOOL actors require at least one tool"

  Scenario: Reject v3 GRAPH actor without route field
    Given a v3 GRAPH actor YAML file without the route field
    When I run the actor add command for "local/no-route-graph" with the prepared config file
    Then v3actor the command should fail
    And v3actor the error message should contain "GRAPH actors require 'route' field"

  Scenario: Reject v3 GRAPH actor without model field
    Given a v3 GRAPH actor YAML file without the model field
    When I run the actor add command for "local/no-model-graph" with the prepared config file
    Then v3actor the command should fail
    And v3actor the error message should contain "GRAPH actors require 'model' field"

  Scenario: Reject v3 actor with invalid type enum
    Given a v3 actor YAML file with invalid type "invalid_type"
    When I run the actor add command for "local/invalid-type" with the prepared config file
    Then v3actor the command should fail
    And v3actor the error message should contain "Input should be 'llm', 'tool' or 'graph'"

  Scenario: Reject v3 actor with invalid context_view enum
    Given a v3 LLM actor YAML file with invalid context_view "invalid_view"
    When I run the actor add command for "local/invalid-view" with the prepared config file
    Then v3actor the command should fail
    And v3actor the error message should contain "context_view"
    And v3actor the error message should contain "Input should be"

  # ────────────────────────────────────────────────────────────
  # Definition of Done: Node ID format validation
  # ────────────────────────────────────────────────────────────

  Scenario: Reject v3 GRAPH actor with invalid node ID format
    Given a v3 GRAPH actor YAML file with an invalid node ID
    When I run the actor add command for "local/bad-node-id" with the prepared config file
    Then v3actor the command should fail
    And v3actor the error message should contain "Node ID must be alphanumeric"

  # ────────────────────────────────────────────────────────────
  # Definition of Done: Tool name namespace validation
  # ────────────────────────────────────────────────────────────

  Scenario: Reject v3 TOOL actor with improperly namespaced tool name
    Given a v3 TOOL actor YAML file with an unnamespaced tool name
    When I run the actor add command for "local/bad-tool-name" with the prepared config file
    Then v3actor the command should fail
    And v3actor the error message should contain "must be namespaced"

  # ────────────────────────────────────────────────────────────
  # Definition of Done: Unreachable node detection
  # ────────────────────────────────────────────────────────────

  Scenario: Reject v3 GRAPH actor with unreachable node
    Given a v3 GRAPH actor YAML file with an unreachable node
    When I run the actor add command for "local/unreachable-node" with the prepared config file
    Then v3actor the command should fail
    And v3actor the error message should contain "unreachable"

  # ────────────────────────────────────────────────────────────
  # v3 Detection and Backward Compatibility
  # ────────────────────────────────────────────────────────────

  Scenario: Detect v3 YAML by type field (llm)
    Given a v3 LLM actor YAML file with name "local/detect-llm"
    When I run the actor add command for "local/detect-llm" with the prepared config file
    Then v3actor the command should succeed
    And the actor should be validated via ActorConfigSchema

  Scenario: Detect v3 YAML by type field (tool)
    Given a v3 TOOL actor YAML file with name "local/detect-tool"
    When I run the actor add command for "local/detect-tool" with the prepared config file
    Then v3actor the command should succeed
    And the actor should be validated via ActorConfigSchema

  Scenario: Detect v3 YAML by type field (graph)
    Given a v3 GRAPH actor YAML file with name "local/detect-graph"
    When I run the actor add command for "local/detect-graph" with the prepared config file
    Then v3actor the command should succeed
    And the actor should be validated via ActorConfigSchema

  # NOTE: The fixture includes both version and type fields so that
  # ActorConfigSchema.model_validate() succeeds. The version-only branch of
  # is_v3_yaml() is exercised by the "Detect v3 YAML by version" direct unit
  # scenarios below (using a config blob with only a version field).
  Scenario: Register v3 actor with both version and type fields
    Given a v3 actor YAML file with version "3.0"
    When I run the actor add command for "local/detect-version" with the prepared config file
    Then v3actor the command should succeed
    And the actor should be validated via ActorConfigSchema

  # ── Backward Compatibility: v2 Actors ─────────────────────────────────────

  Scenario: Register a v2 actor without type field
    Given a v2 actor YAML file with only name, provider, and model fields
    When I run the actor add command for "local/v2-actor" with the prepared config file
    Then v3actor the command should succeed
    And the actor should NOT be validated via ActorConfigSchema

  # ── Update Command v3 Validation ──────────────────────────────────────────

  Scenario: Update a v3 actor with valid YAML succeeds
    Given a registered actor "local/existing-actor" already exists in the registry
    And a v3 LLM actor YAML file with name "local/existing-actor"
    When I run the actor update command for "local/existing-actor" with the prepared config file
    Then v3actor the command should succeed
    And the actor should be validated via ActorConfigSchema

  Scenario: Update a v3 actor with invalid YAML (cycle) fails with error
    Given a registered actor "local/existing-graph" already exists in the registry
    And a v3 GRAPH actor YAML file with a cycle in the route
    When I run the actor update command for "local/existing-graph" with the prepared config file
    Then v3actor the command should fail
    And v3actor the error message should contain "cycle"

  # ────────────────────────────────────────────────────────────
  # is_v3_yaml Version Branch Edge Cases (Fix 2)
  # ────────────────────────────────────────────────────────────

  Scenario: Detect v3 YAML by version "3" (short form)
    Given a config blob with only version field "3"
    When I call is_v3_yaml on the config blob
    Then is_v3_yaml should return True

  Scenario: Do not detect v3 for version "30" (false positive guard)
    Given a config blob with only version field "30"
    When I call is_v3_yaml on the config blob
    Then is_v3_yaml should return False

  Scenario: Do not detect v3 for null type field
    Given a config blob with a null type field
    When I call is_v3_yaml on the config blob
    Then is_v3_yaml should return False

  # ────────────────────────────────────────────────────────────
  # Provider-Required Validation (Fix 5)
  # ────────────────────────────────────────────────────────────

  Scenario: Reject v3 LLM actor without provider field
    Given a v3 LLM actor YAML file without the provider field named "local/no-provider-llm"
    When I run the actor add command for "local/no-provider-llm" with the prepared config file
    Then v3actor the command should fail
    And v3actor the error message should contain "provider"

  Scenario: Reject v3 GRAPH actor without provider field
    Given a v3 GRAPH actor YAML file without the provider field named "local/no-provider-graph"
    When I run the actor add command for "local/no-provider-graph" with the prepared config file
    Then v3actor the command should fail
    And v3actor the error message should contain "provider"

  # NOTE: CLI-level coverage for TOOL actors without provider is deferred.
  # v3 TOOL actors without 'provider' pass ActorConfigSchema validation (tested
  # below via direct schema call) but are rejected by the legacy v2
  # ActorConfiguration.from_blob() canonicalization layer that the CLI invokes.
  # This is a known limitation tracked in follow-up issue:
  # https://git.cleverthis.com/cleveragents/cleveragents-core/issues/9971
  Scenario: Accept valid v3 TOOL actor without provider field (schema level)
    Given a valid v3 TOOL actor YAML without provider for schema validation
    When I validate the TOOL actor YAML blob directly via ActorConfigSchema
    Then the schema validation should succeed

  # ────────────────────────────────────────────────────────────
  # Registry-Level Direct Tests (Fix 6)
  # ────────────────────────────────────────────────────────────

  Scenario: ActorRegistry.add directly rejects v3 GRAPH actor with cycle
    Given a v3 GRAPH actor YAML with a cycle for direct registry testing named "local/registry-cycle-graph"
    When I call ActorRegistry.add directly with the YAML
    Then the registry should raise a ValidationError containing "cycle"

  # ────────────────────────────────────────────────────────────
  # M4: CLI-level test for type: null YAML (falls back to v2 handling)
  # ────────────────────────────────────────────────────────────

  Scenario: v3 actor with null type field falls back to v2 handling
    Given a v3 actor YAML file with null type field
    When I run the actor add command
    Then v3actor the command should succeed
    And the actor should NOT be validated via ActorConfigSchema

  # ────────────────────────────────────────────────────────────
  # M5: Update without --config flag skips schema validation
  # ────────────────────────────────────────────────────────────

  Scenario: Update a registered v3 actor without --config flag skips schema validation
    Given a registered v3 LLM actor
    When I run the actor update command without a config file
    Then v3actor the command should succeed
    And the actor should NOT be validated via ActorConfigSchema

  # ────────────────────────────────────────────────────────────
  # M6: CLI-level test for version "3" without type field
  # ────────────────────────────────────────────────────────────

  Scenario: Reject v3 actor YAML with version "3" but no type field
    Given a v3 actor YAML file with version "3" but no type field
    When I run the actor add command
    Then v3actor the command should fail
    And v3actor the error message should contain "type"

  # ────────────────────────────────────────────────────────────
  # m5: Duplicate node IDs in GRAPH route
  # ────────────────────────────────────────────────────────────

  Scenario: Reject v3 GRAPH actor YAML with duplicate node IDs
    Given a v3 GRAPH actor YAML file with duplicate node IDs
    When I run the actor add command for "local/dup-node-ids" with the prepared config file
    Then v3actor the command should fail
    And v3actor the error message should contain "Duplicate node IDs"

  # ────────────────────────────────────────────────────────────
  # m6: Edge referencing non-existent node
  # ────────────────────────────────────────────────────────────

  Scenario: Reject v3 GRAPH actor YAML with edge referencing non-existent node
    Given a v3 GRAPH actor YAML file with an edge referencing a non-existent node
    When I run the actor add command for "local/bad-edge-ref" with the prepared config file
    Then v3actor the command should fail
    And v3actor the error message should contain "not found"

  # ────────────────────────────────────────────────────────────
  # Nested actors map: combined config.actor field (bug #11189)
  # ────────────────────────────────────────────────────────────

  @tdd_issue @tdd_issue_11189
  Scenario: Register LLM actor using nested actors map with combined config.actor field
    Given a nested LLM actor YAML using combined config.actor field with name "local/nested-combined-llm"
    When I run the actor add command for "local/nested-combined-llm" with the prepared config file
    Then v3actor the command should succeed
    And v3actor the actor should be registered with provider "anthropic" and model "claude-sonnet-4-5"

  Scenario: Explicit config.provider takes precedence over provider derived from config.actor
    Given a nested LLM actor YAML with explicit config.provider overriding config.actor with name "local/explicit-provider-llm"
    When I run the actor add command for "local/explicit-provider-llm" with the prepared config file
    Then v3actor the command should succeed
    And v3actor the actor should be registered with provider "explicit-provider"
    And v3actor the actor should be registered with model "gpt-4"

  Scenario: Nested actors map with no provider or model still raises validation error
    Given a nested LLM actor YAML with no provider or model fields with name "local/no-provider-nested-llm"
    When I run the actor add command for "local/no-provider-nested-llm" with the prepared config file
    Then v3actor the command should fail
    And v3actor the error message should contain "provider"

  Scenario: Explicit config.model takes precedence over model derived from config.actor
    Given a nested LLM actor YAML with explicit config.model overriding config.actor with name "local/explicit-model-llm"
    When I run the actor add command for "local/explicit-model-llm" with the prepared config file
    Then v3actor the command should succeed
    And v3actor the actor should be registered with provider "anthropic"
    And v3actor the actor should be registered with model "explicit-model"

  # ────────────────────────────────────────────────────────────
  # Malformed config.actor edge cases
  # ────────────────────────────────────────────────────────────

  Scenario: Combined config.actor with empty model half is treated as absent
    Given a nested LLM actor YAML with combined config.actor "provider/" and name "local/empty-model-actor"
    When I run the actor add command for "local/empty-model-actor" with the prepared config file
    Then v3actor the command should fail
    And v3actor the error message should contain "provider"

  Scenario: Combined config.actor with empty provider half is treated as missing provider
    Given a nested LLM actor YAML with combined config.actor "/model" and name "local/empty-provider-actor"
    When I run the actor add command for "local/empty-provider-actor" with the prepared config file
    Then v3actor the command should fail
    And v3actor the error message should contain "provider"

  Scenario: Combined config.actor without slash delimiter is treated as absent
    Given a nested LLM actor YAML with combined config.actor "noslash" and name "local/noslash-actor"
    When I run the actor add command for "local/noslash-actor" with the prepared config file
    Then v3actor the command should fail
    And v3actor the error message should contain "provider"

  Scenario: Combined config.actor with both halves empty is treated as absent
    Given a nested LLM actor YAML with combined config.actor "/" and name "local/slash-only-actor"
    When I run the actor add command for "local/slash-only-actor" with the prepared config file
    Then v3actor the command should fail
    And v3actor the error message should contain "provider"
