Feature: Actor configuration uncovered lines coverage
  As a developer maintaining actor configuration parsing
  I want robust coverage for actor config edge cases
  So that failures and overrides are validated

  Background:
    Given an isolated actor config workspace

  # --- load_blob_from_file: lines 39-55 ---

  Scenario: Missing config file surfaces helpful error
    When I load the actor config blob from "missing.json"
    Then a ValueError should be raised containing "Config file not found"

  Scenario: JSON null config becomes empty mapping
    Given an actor config file "null.json" with content:
      """
      null
      """
    When I load the actor config blob from "null.json"
    Then the loaded actor config blob should equal {}

  Scenario: JSON list config raises validation error
    Given an actor config file "list.json" with content:
      """
      [1, 2, 3]
      """
    When I load the actor config blob from "list.json"
    Then a ValueError should be raised containing "Config must be a JSON or YAML object"

  Scenario: Valid JSON config is loaded correctly
    Given an actor config file "valid.json" with content:
      """
      {"provider": "openai", "model": "gpt-4"}
      """
    When I load the actor config blob from "valid.json"
    Then the loaded actor config blob should equal {"provider": "openai", "model": "gpt-4"}

  # --- _load_v2_yaml_content: lines 59-60 (yaml unavailable) ---

  Scenario: YAML dependency absence surfaces requirement
    Given PyYAML parsing is unavailable for actor config
    And an actor config file "needs_yaml.yaml" with content:
      """
      provider: openai
      """
    When I load the actor config blob from "needs_yaml.yaml"
    Then a ValueError should be raised containing "PyYAML is required for YAML actor configs"

  # --- _load_v2_yaml_content: lines 63-106 (YAML parsing paths) ---

  Scenario: Empty YAML returns empty object
    Given an actor config file "empty.yaml" with content:
      """
      """
    When I load the actor config blob from "empty.yaml"
    Then the loaded actor config blob should equal {}

  Scenario: Non-object YAML raises validation error
    Given an actor config file "list.yaml" with content:
      """
      - provider: openai
      """
    When I load the actor config blob from "list.yaml"
    Then a ValueError should be raised containing "Config must be a JSON or YAML object"

  Scenario: Plain YAML config is loaded via safe_load path
    Given an actor config file "plain.yaml" with content:
      """
      provider: openai
      model: gpt-4
      """
    When I load the actor config blob from "plain.yaml"
    Then the loaded actor config blob should equal {"provider": "openai", "model": "gpt-4"}

  # --- _load_v2_yaml_content: lines 64-92 (templated YAML branch) ---

  Scenario: Templated YAML preserves double-brace placeholders in system_prompt
    Given an actor config file "templated.yaml" with content:
      """
      provider: openai
      model: gpt-4
      system_prompt: "Use {{ context.paper_details.topic }} to write."
      """
    When I load the actor config blob from "templated.yaml"
    Then the loaded actor config value at "system_prompt" should equal "Use {{ context.paper_details.topic }} to write."

  Scenario: Templated YAML preserves block-tag placeholders in system_prompt
    Given an actor config file "block_template.yaml" with content:
      """
      provider: openai
      model: gpt-4
      system_prompt: "{% if context.brainstorming_summary %}summary{% endif %}"
      """
    When I load the actor config blob from "block_template.yaml"
    Then the loaded actor config value at "system_prompt" should contain "summary"

  # --- _restore_template_syntax: lines 110-130 (dict and list recursion) ---

  Scenario: Restore template syntax recurses into nested dicts
    Given an actor config file "nested_template.yaml" with content:
      """
      provider: openai
      model: gpt-4
      outer:
        system_prompt: "Hello {{ context.paper_details.topic }}"
      """
    When I load the actor config blob from "nested_template.yaml"
    Then the loaded actor config nested value at "outer.system_prompt" should equal "Hello {{ context.paper_details.topic }}"

  Scenario: Restore template syntax recurses into lists
    Given an actor config file "list_template.yaml" with content:
      """
      provider: openai
      model: gpt-4
      messages:
        - role: system
          system_prompt: "Topic is {{ context.paper_details.topic }}"
        - role: user
          content: "plain text"
      """
    When I load the actor config blob from "list_template.yaml"
    Then the loaded actor config nested value at "messages.0.system_prompt" should equal "Topic is {{ context.paper_details.topic }}"

  # --- _interpolate_env_vars: lines 134-174 (env var substitution and type coercion) ---

  Scenario: Environment variable interpolation uses default boolean value
    Given an actor config file "env_bool.yaml" with content:
      """
      provider: openai
      model: gpt-4
      options:
        flag: "${MISSING_BOOL_VAR:true}"
      """
    And the actor config environment variable "MISSING_BOOL_VAR" is unset
    When I load the actor config blob from "env_bool.yaml"
    Then the loaded actor config value at "options.flag" should equal True

  Scenario: Environment variable interpolation uses default false boolean value
    Given an actor config file "env_false.yaml" with content:
      """
      provider: openai
      model: gpt-4
      options:
        flag: "${MISSING_BOOL_FALSE:false}"
      """
    And the actor config environment variable "MISSING_BOOL_FALSE" is unset
    When I load the actor config blob from "env_false.yaml"
    Then the loaded actor config value at "options.flag" should equal False

  Scenario: Environment variable interpolation uses default integer value
    Given an actor config file "env_int.yaml" with content:
      """
      provider: openai
      model: gpt-4
      options:
        count: "${MISSING_INT_VAR:42}"
      """
    And the actor config environment variable "MISSING_INT_VAR" is unset
    When I load the actor config blob from "env_int.yaml"
    Then the loaded actor config value at "options.count" should equal 42

  Scenario: Environment variable interpolation uses default string value
    Given an actor config file "env_str.yaml" with content:
      """
      provider: openai
      model: gpt-4
      options:
        greeting: "${MISSING_STR_VAR:hello}"
      """
    And the actor config environment variable "MISSING_STR_VAR" is unset
    When I load the actor config blob from "env_str.yaml"
    Then the loaded actor config value at "options.greeting" should equal "hello"

  Scenario: Environment variable interpolation uses default float value
    Given an actor config file "env_float.yaml" with content:
      """
      provider: openai
      model: gpt-4
      options:
        ratio: "${MISSING_FLOAT_VAR:2.5}"
      """
    And the actor config environment variable "MISSING_FLOAT_VAR" is unset
    When I load the actor config blob from "env_float.yaml"
    Then the loaded actor config value at "options.ratio" should equal 2.5

  Scenario: Environment variable interpolation reads set env var
    Given an actor config file "env_set.yaml" with content:
      """
      provider: openai
      model: gpt-4
      options:
        api_key: "${TEST_ACTOR_API_KEY}"
      """
    And the actor config environment variable "TEST_ACTOR_API_KEY" is set to "secret123"
    When I load the actor config blob from "env_set.yaml"
    Then the loaded actor config value at "options.api_key" should equal "secret123"

  Scenario: Missing required environment variable raises an error
    Given an actor config file "required_env.yaml" with content:
      """
      provider: openai
      model: gpt-4
      secret: "${REQUIRED_SECRET}"
      """
    And the actor config environment variable "REQUIRED_SECRET" is unset
    When I load the actor config blob from "required_env.yaml"
    Then a ValueError should be raised containing "Environment variable 'REQUIRED_SECRET' is not set"

  Scenario: Environment variable coerces top-level string true to boolean
    Given an actor config file "env_top_bool.yaml" with content:
      """
      provider: openai
      model: gpt-4
      enabled: true
      """
    When I load the actor config blob from "env_top_bool.yaml"
    Then the loaded actor config value at "enabled" should equal True

  Scenario: Environment variable coerces string integer to int
    Given an actor config file "env_top_int.yaml" with content:
      """
      provider: openai
      model: gpt-4
      retries: 3
      """
    When I load the actor config blob from "env_top_int.yaml"
    Then the loaded actor config value at "retries" should equal 3

  Scenario: Interpolation coerces negative integer default
    Given an actor config file "env_neg_int.yaml" with content:
      """
      provider: openai
      model: gpt-4
      options:
        offset: "${MISSING_NEG_INT:-5}"
      """
    And the actor config environment variable "MISSING_NEG_INT" is unset
    When I load the actor config blob from "env_neg_int.yaml"
    Then the loaded actor config value at "options.offset" should equal -5

  Scenario: Interpolation recurses into nested dicts and lists
    Given an actor config file "env_nested.yaml" with content:
      """
      provider: openai
      model: gpt-4
      options:
        items:
          - "${MISSING_ITEM_VAR:default_item}"
      """
    And the actor config environment variable "MISSING_ITEM_VAR" is unset
    When I load the actor config blob from "env_nested.yaml"
    Then the loaded actor config nested value at "options.items.0" should equal "default_item"

  # --- from_file: lines 189-190 ---

  Scenario: from_file applies overrides and unsafe flag
    Given an actor config file "valid_ff.json" with content:
      """
      {"provider": "file-provider", "model": "file-model", "options": {"k": "v"}, "graph_descriptor": {"node": true}}
      """
    When I parse the actor configuration from file "valid_ff.json" with overrides:
      """
      {"name": "cli-name", "graph_descriptor": {"node": "override"}, "unsafe": true}
      """
    Then the actor configuration should have provider "file-provider" and model "file-model"
    And the actor configuration name should be "cli-name"
    And the actor configuration graph descriptor should equal {"node": "override"}
    And the actor configuration options should equal {"k": "v"}
    And the actor configuration unsafe flag should be true

  # --- from_blob: lines 236 (default_options), 238 (v2_options), 250 (missing model) ---

  Scenario: from_blob rejects missing provider
    When I build an actor configuration from blob {"model": "only-model"}
    Then a ValueError should be raised containing "provider is required"

  Scenario: from_blob rejects missing model
    When I build an actor configuration from blob {"provider": "only-provider"}
    Then a ValueError should be raised containing "model is required"

  Scenario: from_blob merges default and v2 and override options
    When I build an actor configuration from structured blob with defaults and overrides:
      """
      {
        "blob": {
          "provider": "cli-provider",
          "model": "cli-model",
          "options": {"user": "blob"},
          "agents": {
            "writer": {
              "config": {
                "options": {"v2": "v2-option"}
              }
            }
          }
        },
        "default_options": {"base": "default"},
        "option_overrides": {"user": "override", "extra": "added"}
      }
      """
    Then the actor configuration should have provider "cli-provider" and model "cli-model"
    And the actor configuration options should equal {"base": "default", "v2": "v2-option", "user": "override", "extra": "added"}

  Scenario: from_blob with None blob defaults to empty data
    When I build actor config from None blob with provider and model overrides
    Then the actor configuration should have provider "override-provider" and model "override-model"

  # --- _extract_v2_actor: lines 275-307 ---

  Scenario: v2 YAML actor config infers provider and model
    Given an actor config file "v2.yaml" with content:
      """
      cleveragents:
        default_router: main_router
      agents:
        paper_writer:
          type: llm
          config:
            provider: openai
            model: gpt-4
            unsafe: true
            options:
              temperature: 0.5
      routes:
        main_router:
          type: stream
          operators:
            - type: map
              params:
                agent: paper_writer
          publications:
            - __output__
      """
    When I parse the actor configuration from file "v2.yaml" with overrides:
      """
      {}
      """
    Then the actor configuration should have provider "openai" and model "gpt-4"
    And the actor configuration unsafe flag should be true
    And the actor configuration graph descriptor should include key "routes"
    And the actor configuration graph descriptor should include key "agents"
    And the actor configuration graph descriptor should include key "cleveragents"
    And the actor configuration options should equal {"temperature": 0.5}

  Scenario: v2 extraction includes merges and templates keys when present
    Given an actor config file "v2_merges.yaml" with content:
      """
      agents:
        writer:
          config:
            provider: openai
            model: gpt-4
      merges:
        combined:
          type: join
      templates:
        default:
          system_prompt: "hello"
      """
    When I parse the actor configuration from file "v2_merges.yaml" with overrides:
      """
      {}
      """
    Then the actor configuration should have provider "openai" and model "gpt-4"
    And the actor configuration graph descriptor should include key "merges"
    And the actor configuration graph descriptor should include key "templates"

  Scenario: v2 extraction handles agent entry without config block
    Given an actor config file "v2_no_config.yaml" with content:
      """
      provider: fallback-provider
      model: fallback-model
      agents:
        first:
          type: llm
      """
    When I parse the actor configuration from file "v2_no_config.yaml" with overrides:
      """
      {}
      """
    Then the actor configuration should have provider "fallback-provider" and model "fallback-model"

  # --- _extract_v2_options: lines 316-326 ---

  Scenario: v2 extraction skips non-dict agent entries
    Given an actor config file "invalid_v2.yaml" with content:
      """
      provider: fallback-provider
      model: fallback-model
      agents:
        first: not-a-dict
      """
    When I parse the actor configuration from file "invalid_v2.yaml" with overrides:
      """
      {}
      """
    Then the actor configuration should have provider "fallback-provider" and model "fallback-model"

  Scenario: v2 options extraction returns None for agents without options
    Given an actor config file "v2_no_opts.yaml" with content:
      """
      agents:
        writer:
          config:
            provider: openai
            model: gpt-4
      """
    When I parse the actor configuration from file "v2_no_opts.yaml" with overrides:
      """
      {}
      """
    Then the actor configuration should have provider "openai" and model "gpt-4"
    And the actor configuration options should equal {}

  Scenario: from_blob reads provider_type and model_id aliases
    When I build an actor configuration from blob {"provider_type": "aliased-provider", "model_id": "aliased-model"}
    Then the actor configuration should have provider "aliased-provider" and model "aliased-model"

  Scenario: from_blob resolves graph from graph key alias
    When I build actor config from blob using graph key alias
    Then the actor configuration graph descriptor should equal {"step": "one"}

  Scenario: from_blob sets unsafe from blob data
    When I build an actor configuration from blob {"provider": "p", "model": "m", "unsafe": True}
    Then the actor configuration should have provider "p" and model "m"
    And the actor configuration unsafe flag should be true

  Scenario: from_blob with non-dict graph coerces to None
    When I build an actor configuration from blob {"provider": "p", "model": "m", "graph_descriptor": "not-a-dict"}
    Then the actor configuration should have provider "p" and model "m"
    And the actor configuration graph descriptor should be None
