Files
cleveragents-core/features/actor_config_coverage.feature
CoreRasurae 78be08870c
CI / lint (push) Successful in 1m10s
CI / quality (push) Successful in 1m16s
CI / build (push) Successful in 1m1s
CI / benchmark-regression (push) Has been skipped
CI / typecheck (push) Successful in 1m46s
CI / security (push) Successful in 1m58s
CI / push-validation (push) Successful in 43s
CI / helm (push) Successful in 47s
CI / e2e_tests (push) Successful in 4m9s
CI / integration_tests (push) Successful in 5m9s
CI / unit_tests (push) Successful in 7m45s
CI / docker (push) Successful in 1m49s
CI / coverage (push) Successful in 14m18s
CI / status-check (push) Successful in 3s
CI / benchmark-publish (push) Successful in 1h31m39s
CI / lint (pull_request) Successful in 1m17s
CI / typecheck (pull_request) Successful in 1m30s
CI / benchmark-publish (pull_request) Has been skipped
CI / security (pull_request) Successful in 1m33s
CI / push-validation (pull_request) Successful in 48s
CI / helm (pull_request) Successful in 49s
CI / build (pull_request) Successful in 1m32s
CI / benchmark-regression (pull_request) Failing after 2m1s
CI / quality (pull_request) Successful in 2m9s
CI / e2e_tests (pull_request) Successful in 4m58s
CI / integration_tests (pull_request) Successful in 5m23s
CI / unit_tests (pull_request) Successful in 6m43s
CI / docker (pull_request) Successful in 1m36s
CI / coverage (pull_request) Successful in 10m58s
CI / status-check (pull_request) Successful in 5s
fix(cli): validate actor provider field at correct config nesting level
- Actor configuration in V3 is now obtained from the nested configuration parameter, according to the specification.
- Removed the legacy V2 fallback support and the tests affected by that removal. Mocked existing steps to allow remaining V2 features to be covered/tested.
- Fix add() to pass unsafe flag to add_v3() for proper unsafe actor handling
- Add _extract_nested_v3_config() to extract provider/model from nested
  actors.<name>.config block before v3 schema validation
- Remove v2 extraction test scenarios from consolidated_actor.feature
  that call removed _extract_v2_actor() and _extract_v2_options() methods
- Update test YAML in actor_registry_spec_yaml_steps.py to exercise nested type detection (no top-level type field)
- Add @tdd_issue_4300 regression test tag to existing spec-compliant
  actors map scenario

ISSUES CLOSED: #4300
2026-05-09 23:13:33 +01:00

303 lines
12 KiB
Gherkin

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 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"
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