Feature: Consolidated Config Combined scenarios from: config_parser_coverage, config_resolution, config_service_coverage, coverage_threshold_config # ============================================================ # Originally from: config_parser_coverage.feature # Feature: Reactive config parser coverage # ============================================================ Scenario: Parse combined configs with merges, routes, and pipelines Given a temporary directory for reactive config parsing Given reactive config files covering merges, routes, and pipelines When I parse the reactive config files Then the merged reactive config should preserve agents and replacements And stream and graph routes should be built with defaults and bridges And reactive config should include merges splits pipelines and templates Scenario: Interpolate environment variables with defaults Given a temporary directory for reactive config parsing Given a reactive config file with environment placeholders And environment variables are set for interpolation When I parse the reactive config files Then environment placeholders should resolve using values and defaults Scenario: Raise error for missing required environment variable Given a temporary directory for reactive config parsing Given a reactive config file with a required environment placeholder When I parse the reactive config files expecting failure Then a configuration error should be raised for the missing variable # ============================================================ # Originally from: config_resolution.feature # Feature: Config service with multi-level resolution # ============================================================ Scenario: Default value is returned when nothing else is set Given a clean config service test environment When I resolve config key "core.log.level" Then the resolved value should be "FATAL" And the resolved source should be "default" Scenario: Global config file overrides default Given a clean config service test environment Given I have written global config key "core.log.level" with value "DEBUG" When I resolve config key "core.log.level" Then the resolved value should be "DEBUG" And the resolved source should be "global" Scenario: Environment variable overrides global config Given a clean config service test environment Given I have written global config key "core.log.level" with value "DEBUG" And the environment variable "CLEVERAGENTS_LOG_LEVEL" is set to "WARNING" When I resolve config key "core.log.level" Then the resolved value should be "WARNING" And the resolved source should be "env_var" Scenario: CLI flag overrides environment variable Given a clean config service test environment Given the environment variable "CLEVERAGENTS_LOG_LEVEL" is set to "WARNING" When I resolve config key "core.log.level" with CLI value "ERROR" Then the resolved value should be "ERROR" And the resolved source should be "cli_flag" Scenario: Project-scoped value overrides global config Given a clean config service test environment Given I have written global config key "core.automation-profile" with value "review" And I have written project "myproj" config key "core.automation-profile" with value "trusted" When I resolve config key "core.automation-profile" for project "myproj" Then the resolved value should be "trusted" And the resolved source should be "project" Scenario: Env var still overrides project-scoped value Given a clean config service test environment Given I have written project "myproj" config key "core.automation-profile" with value "trusted" And the environment variable "CLEVERAGENTS_AUTOMATION_PROFILE" is set to "manual" When I resolve config key "core.automation-profile" for project "myproj" Then the resolved value should be "manual" And the resolved source should be "env_var" # --- Env var interpolation --- Scenario: Env var name matches CLEVERAGENTS convention Given a clean config service test environment When I look up the env var for key "core.log.level" Then the env var name should be "CLEVERAGENTS_LOG_LEVEL" Scenario: Env var interpolation for plan keys Given a clean config service test environment When I look up the env var for key "plan.concurrency" Then the env var name should be "CLEVERAGENTS_PLAN_CONCURRENCY" Scenario: Env var interpolation for plan budget keys Given a clean config service test environment When I look up the env var for key "plan.budget.warn-threshold" Then the env var name should be "CLEVERAGENTS_PLAN_BUDGET_WARN" Scenario: Provider keys use custom env var names Given a clean config service test environment When I look up the env var for key "provider.openai.api-key" Then the env var name should be "OPENAI_API_KEY" # --- Unknown key rejection --- Scenario: Resolving an unknown key raises an error Given a clean config service test environment When I attempt to resolve unknown key "bogus.nonexistent" Then the config ValueError message should contain "Unknown configuration key" Scenario: Validating an unknown key raises an error Given a clean config service test environment When I attempt to validate unknown key "invalid.key" Then the config ValueError message should contain "Unknown configuration key" # --- Type validation --- Scenario: Integer value is coerced from string Given a clean config service test environment Given the environment variable "CLEVERAGENTS_PLAN_CONCURRENCY" is set to "9090" When I resolve config key "plan.concurrency" Then the resolved value should be integer 9090 Scenario: Boolean value true is coerced from string Given a clean config service test environment Given the environment variable "CLEVERAGENTS_LOG_FILE_ENABLED" is set to "true" When I resolve config key "core.log.file-enabled" Then the resolved value should be boolean true Scenario: Boolean value false is coerced from string Given a clean config service test environment Given the environment variable "CLEVERAGENTS_LOG_FILE_ENABLED" is set to "false" When I resolve config key "core.log.file-enabled" Then the resolved value should be boolean false Scenario: Float value is coerced from string Given a clean config service test environment Given the environment variable "CLEVERAGENTS_PLAN_BUDGET_WARN" is set to "0.9" When I resolve config key "plan.budget.warn-threshold" Then the resolved value should be float 0.9 Scenario: Invalid boolean string raises TypeError Given a clean config service test environment When I attempt to validate type for key "core.log.file-enabled" with value "notabool" Then the config TypeError message should contain "Cannot convert" Scenario: Invalid integer string raises TypeError Given a clean config service test environment When I attempt to validate type for key "plan.concurrency" with value "notanumber" Then the config TypeError message should contain "Type mismatch" # --- Verbose resolution chain --- Scenario: Verbose mode returns full resolution chain Given a clean config service test environment When I resolve config key "core.log.level" with verbose mode Then the resolution chain should have 6 entries And the chain should include source "cli_flag" And the chain should include source "env_var" And the chain should include source "local" And the chain should include source "project" And the chain should include source "global" And the chain should include source "default" # --- Key registry --- Scenario: Registry contains core keys Given a clean config service test environment Then the registry should contain key "core.log.level" And the registry should contain key "core.log.file-enabled" And the registry should contain key "core.data-dir" Scenario: Registry contains plan keys Given a clean config service test environment Then the registry should contain key "plan.concurrency" And the registry should contain key "plan.max-child-depth" And the registry should contain key "plan.budget.per-plan" Scenario: Registry contains provider keys Given a clean config service test environment Then the registry should contain key "provider.openai.api-key" And the registry should contain key "provider.anthropic.api-key" Scenario: Registry contains sandbox keys Given a clean config service test environment Then the registry should contain key "sandbox.strategy" And the registry should contain key "sandbox.cleanup" And the registry should contain key "sandbox.checkpoint.enabled" Scenario: Registry contains context keys Given a clean config service test environment Then the registry should contain key "context.hot.max-tokens" And the registry should contain key "context.warm.max-decisions" Scenario: Registry contains index keys Given a clean config service test environment Then the registry should contain key "index.auto-reindex" And the registry should contain key "index.text.backend" Scenario: Registry contains server keys Given a clean config service test environment Then the registry should contain key "server.url" And the registry should contain key "server.token" And the registry should contain key "server.sync.auto" Scenario: Registry contains actor keys Given a clean config service test environment Then the registry should contain key "actor.default.strategy" And the registry should contain key "actor.default.execution" # --- TOML file management --- Scenario: Writing and reading TOML config roundtrips Given a clean config service test environment Given I write config data with key "core.log.level" and value "TRACE" When I read the config file Then the config data should contain key "core.log.level" with value "TRACE" Scenario: Config directory is auto-created Given a clean config service test environment When I write config data to a new directory Then the config directory should exist Scenario: Non-project-scopable keys ignore project scope Given a clean config service test environment Given I have written project "proj" config key "core.data-dir" with value "/tmp/other" When I resolve config key "core.data-dir" for project "proj" Then the resolved source should be "default" # --- Resolve all --- Scenario: Resolve all returns all registered keys Given a clean config service test environment When I resolve all keys Then the result should contain all registered keys # --- Set value --- Scenario: Set value persists to TOML file Given a clean config service test environment When I set config value "core.log.level" to "CRITICAL" And I read the config file Then the config data should contain key "core.log.level" with value "CRITICAL" # --- Entry lookup --- Scenario: Get entry returns ConfigEntry for valid key Given a clean config service test environment When I get entry for key "core.log.level" Then the entry should have section "core" And the entry should have python type "str" Scenario: Get entry returns None for unknown key Given a clean config service test environment When I get entry for key "nonexistent.key" Then the entry should be None # ============================================================ # Originally from: config_service_coverage.feature # Feature: ConfigService full coverage # ============================================================ Scenario: ConfigLevel enum has six precedence levels Then ConfigLevel should have values CLI_FLAG ENV_VAR LOCAL PROJECT GLOBAL DEFAULT # ---------- ConfigEntry and ResolvedValue dataclasses ---------- Scenario: ConfigEntry dataclass stores all metadata fields Given a ConfigEntry with key "test.key" and type str Then the ConfigEntry fields should match the provided values Scenario: ResolvedValue dataclass stores resolution result Given a ResolvedValue with key "test.key" and source DEFAULT Then the ResolvedValue fields should match including an empty chain by default # ---------- _env_name helper ---------- Scenario: _env_name builds uppercase CLEVERAGENTS env var name When I call _env_name with section "core" and key "log_level" Then the env name should be "CLEVERAGENTS_CORE_LOG_LEVEL" # ---------- _register and _build_catalog ---------- Scenario: _register adds an entry to the global registry When I register a custom key "custom.test_key" with type int and default 42 Then the registry should contain "custom.test_key" with default 42 Scenario: _register uses explicit env_var when provided When I register a key "custom.explicit_env" with explicit env_var "MY_CUSTOM_VAR" Then the entry "custom.explicit_env" should have env_var "MY_CUSTOM_VAR" Scenario: _build_catalog populates all expected config sections Then the registry should contain keys from sections core plan provider sandbox context index Scenario: _build_catalog registers the expected number of keys Then the registry should contain at least 20 keys # ---------- ConfigService instantiation ---------- Scenario: ConfigService uses custom config_dir and config_path Given a temporary directory for config service When I create a ConfigService with custom paths Then the service should use the custom config directory and path Scenario: ConfigService uses defaults when no paths provided When I create a ConfigService with default paths Then the service config path should end with ".cleveragents/config.toml" # ---------- registry(), get_entry(), registered_keys() ---------- Scenario: registry returns a copy of all registered entries When I call ConfigService.registry Then it should return a dict with the same keys as the internal registry Scenario: get_entry returns the entry for a known key When I call ConfigService.get_entry with "core.log.level" Then it should return a ConfigEntry with key "core.log.level" Scenario: get_entry returns None for an unknown key When I call ConfigService.get_entry with "nonexistent.key" Then it should return None Scenario: registered_keys returns a sorted list of all keys When I call ConfigService.registered_keys Then it should return a sorted list containing "core.log.level" # ---------- read_config ---------- Scenario: read_config returns empty dict when file does not exist Given a temporary directory for config service When I create a ConfigService pointing to a missing config file Then read_config should return an empty dict Scenario: read_config parses an existing TOML file Given a temporary directory for config service And a TOML config file with key "core.log.level" set to "DEBUG" When I create a ConfigService pointing to that TOML file Then read_config should return a dict with "core.log.level" equal to "DEBUG" # ---------- write_config ---------- Scenario: write_config creates directories and writes a new TOML file Given a temporary directory for config service When I create a ConfigService with a nested non-existent config directory And I call write_config with key "greeting" value "hello" Then the TOML file should exist and contain key "greeting" with value "hello" Scenario: write_config merges data into an existing TOML file Given a temporary directory for config service And a TOML config file with key "existing" set to "value1" When I create a ConfigService pointing to that TOML file And I call write_config with key "new_key" value "value2" Then read_config should return a dict containing both "existing" and "new_key" # ---------- set_value ---------- Scenario: set_value persists a single key-value pair Given a temporary directory for config service When I create a ConfigService with custom paths And I call set_value with key "mykey" and value "myval" Then read_config should return a dict with "mykey" equal to "myval" # ---------- validate_key ---------- Scenario: validate_key returns entry for a known key When I call validate_key with "core.log.level" Then it should return the ConfigEntry for "core.log.level" without error Scenario: validate_key raises ValueError for an unknown key When I call validate_key with "totally.unknown" Then a ValueError should be raised mentioning "Unknown configuration key" # ---------- validate_type ---------- Scenario: validate_type returns value unchanged when type already matches When I call validate_type with key "core.log.level" and value "INFO" Then it should return "INFO" unchanged Scenario: validate_type coerces a string to int When I call validate_type with key "plan.concurrency" and string value "9090" Then it should return the integer 9090 Scenario: validate_type coerces a string to float When I call validate_type with key "plan.budget.warn-threshold" and string value "0.5" Then it should return the float 0.5 Scenario: validate_type coerces non-string to str When I call validate_type with key "core.log.level" and integer value 123 Then it should return the string "123" Scenario: validate_type coerces "true" string to bool True When I call validate_type with key "core.log.file-enabled" and string value "true" Then it should return boolean True Scenario: validate_type coerces "1" string to bool True When I call validate_type with key "core.log.file-enabled" and string value "1" Then it should return boolean True Scenario: validate_type coerces "yes" string to bool True When I call validate_type with key "core.log.file-enabled" and string value "yes" Then it should return boolean True Scenario: validate_type coerces "false" string to bool False When I call validate_type with key "core.log.file-enabled" and string value "false" Then it should return boolean False Scenario: validate_type coerces "0" string to bool False When I call validate_type with key "core.log.file-enabled" and string value "0" Then it should return boolean False Scenario: validate_type coerces "no" string to bool False When I call validate_type with key "core.log.file-enabled" and string value "no" Then it should return boolean False Scenario: validate_type raises TypeError for invalid bool string When I call validate_type with key "core.log.file-enabled" and string value "maybe" Then a TypeError should be raised mentioning "Cannot convert" Scenario: validate_type raises TypeError for non-coercible int value When I call validate_type with key "plan.concurrency" and string value "not_a_number" Then a TypeError should be raised mentioning "Type mismatch" Scenario: validate_type raises TypeError for non-bool non-string to bool key When I call validate_type with key "core.log.file-enabled" and a list value Then a TypeError should be raised mentioning "Type mismatch" Scenario: validate_type raises ValueError for completely unknown key When I call validate_type with unknown key "fake.unknown" and value "x" Then the raised ValueError should mention "Cannot validate type for unknown key" # ---------- resolve: six-level chain ---------- Scenario: resolve returns default value when no overrides exist Given a temporary directory for config service And a ConfigService with empty config for resolve tests When I resolve key "core.log.level" with no overrides Then the resolved value should be "FATAL" from source DEFAULT Scenario: resolve returns CLI flag value when provided Given a temporary directory for config service And a ConfigService with empty config for resolve tests When I resolve key "core.log.level" with cli_value "TRACE" Then the resolved value should be "TRACE" from source CLI_FLAG Scenario: resolve returns environment variable when no CLI flag Given a temporary directory for config service And a ConfigService with empty config for resolve tests And the env var "CLEVERAGENTS_LOG_LEVEL" is injected with "WARNING" When I resolve key "core.log.level" with no overrides Then the resolved value should be "WARNING" from source ENV_VAR Scenario: CLI flag takes precedence over environment variable Given a temporary directory for config service And a ConfigService with empty config for resolve tests And the env var "CLEVERAGENTS_LOG_LEVEL" is injected with "WARNING" When I resolve key "core.log.level" with cli_value "TRACE" Then the resolved value should be "TRACE" from source CLI_FLAG Scenario: resolve returns project-scoped value when set Given a temporary directory for config service And a ConfigService with project-scoped config for key "core.automation-profile" value "PROJECT_DEBUG" under project "myproj" When I resolve key "core.automation-profile" with project_name "myproj" Then the resolved value should be "PROJECT_DEBUG" from source PROJECT Scenario: resolve returns global config value when no higher overrides Given a temporary directory for config service And a ConfigService with global config key "core.log.level" set to "GLOBAL_WARN" When I resolve key "core.log.level" with no overrides Then the resolved value should be "GLOBAL_WARN" from source GLOBAL Scenario: resolve populates chain when verbose is True Given a temporary directory for config service And a ConfigService with empty config for resolve tests When I resolve key "core.log.level" with verbose True and no overrides Then the resolved chain should have 6 entries covering all levels Scenario: resolve verbose chain includes env_name for ENV_VAR level Given a temporary directory for config service And a ConfigService with empty config for resolve tests When I resolve key "core.log.level" with verbose True and no overrides Then the verbose chain ENV_VAR entry should include env_name "CLEVERAGENTS_LOG_LEVEL" Scenario: resolve verbose chain includes path for GLOBAL level Given a temporary directory for config service And a ConfigService with empty config for resolve tests When I resolve key "core.log.level" with verbose True and no overrides Then the verbose chain GLOBAL entry should include the config file path Scenario: resolve verbose chain shows project value when project-scoped wins Given a temporary directory for config service And a ConfigService with project-scoped config for key "core.automation-profile" value "PROJECT_DEBUG" under project "myproj" When I resolve key "core.automation-profile" with project_name "myproj" and verbose True Then the resolved value should be "PROJECT_DEBUG" from source PROJECT And the verbose chain PROJECT entry should have value "PROJECT_DEBUG" Scenario: resolve verbose chain shows global value when global config wins Given a temporary directory for config service And a ConfigService with global config key "core.log.level" set to "GLOBAL_WARN" When I resolve key "core.log.level" with verbose True and no overrides Then the resolved value should be "GLOBAL_WARN" from source GLOBAL And the verbose chain GLOBAL entry should have value "GLOBAL_WARN" Scenario: resolve skips project scope for non-scopable keys Given a temporary directory for config service And a ConfigService with project-scoped config for key "core.data-dir" value "/proj/data" under project "myproj" When I resolve key "core.data-dir" with project_name "myproj" Then the resolved value should not be "/proj/data" And the resolved source should be DEFAULT or GLOBAL # ---------- env_var_for_key ---------- Scenario: env_var_for_key returns the env var name for a valid key When I call env_var_for_key with "core.log.level" Then it should return "CLEVERAGENTS_LOG_LEVEL" Scenario: env_var_for_key raises ValueError for an unknown key When I call env_var_for_key with "nonexistent.key" Then a ValueError should be raised mentioning "Unknown configuration key" # ---------- resolve_all ---------- Scenario: resolve_all returns a resolved value for every registered key Given a temporary directory for config service And a ConfigService with empty config for resolve tests When I call resolve_all with no overrides Then the result should contain an entry for every registered key Scenario: resolve_all applies CLI overrides to matching keys Given a temporary directory for config service And a ConfigService with empty config for resolve tests When I call resolve_all with cli_override "core.log.level" set to "FATAL" Then the resolve_all result for "core.log.level" should have value "FATAL" and source CLI_FLAG # ============================================================ # Originally from: coverage_threshold_config.feature # Feature: Coverage threshold configuration enforcement # ============================================================ Scenario: Coverage configuration exists in pyproject.toml Given the pyproject toml file is loaded for coverage check Then the coverage run section should exist And the coverage source should include "src" And the coverage branch tracking should be enabled @tdd_issue @tdd_issue_4227 Scenario: Coverage threshold is at least 96.5 percent in noxfile Given the noxfile py is loaded for coverage check Then the noxfile should contain a fail-under threshold of at least 96.5 Scenario: Coverage report session exists in noxfile Given the noxfile py is loaded for coverage check Then the noxfile should define a coverage_report session Scenario: Coverage HTML output directory is configured Given the pyproject toml file is loaded for coverage check Then the coverage html directory should be "build/htmlcov" Scenario: Coverage XML output path is configured Given the pyproject toml file is loaded for coverage check Then the coverage xml output should be "build/coverage.xml" Scenario: Coverage data file path is configured Given the pyproject toml file is loaded for coverage check Then the coverage data file should be "build/.coverage" Scenario: Coverage omits test directories Given the pyproject toml file is loaded for coverage check Then the coverage omit patterns should include "features/*" And the coverage omit patterns should include "*/tests/*" Scenario: CI workflow enforces coverage via nox session Given the ci workflow file is loaded for coverage check Then the ci workflow should reference nox coverage_report session Scenario: Nightly workflow uses at least 96.5 percent threshold Given the nightly quality workflow file is loaded for coverage check Then the nightly workflow should use a fail-under of at least 96.5