Feature: Config service with multi-level resolution As a developer I want a config service that resolves values through a precedence chain So that CLI flags, env vars, project scope, global config, and defaults all work correctly Background: Given a clean config service test environment # --- Resolution levels --- Scenario: Default value is returned when nothing else is set When I resolve config key "core.log_level" Then the resolved value should be "INFO" And the resolved source should be "default" Scenario: Global config file overrides default 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 I have written global config key "core.log_level" with value "DEBUG" And the environment variable "CLEVERAGENTS_CORE_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 the environment variable "CLEVERAGENTS_CORE_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 I have written global config key "core.log_level" with value "DEBUG" And I have written project "myproj" config key "core.log_level" with value "TRACE" When I resolve config key "core.log_level" for project "myproj" Then the resolved value should be "TRACE" And the resolved source should be "project" Scenario: Env var still overrides project-scoped value Given I have written project "myproj" config key "core.log_level" with value "TRACE" And the environment variable "CLEVERAGENTS_CORE_LOG_LEVEL" is set to "ERROR" When I resolve config key "core.log_level" for project "myproj" Then the resolved value should be "ERROR" And the resolved source should be "env_var" # --- Env var interpolation --- Scenario: Env var name matches CLEVERAGENTS convention When I look up the env var for key "core.log_level" Then the env var name should be "CLEVERAGENTS_CORE_LOG_LEVEL" Scenario: Env var interpolation for plan keys When I look up the env var for key "plan.max_retries" Then the env var name should be "CLEVERAGENTS_PLAN_MAX_RETRIES" Scenario: Env var interpolation for provider keys When I look up the env var for key "provider.temperature" Then the env var name should be "CLEVERAGENTS_PROVIDER_TEMPERATURE" # --- Unknown key rejection --- Scenario: Resolving an unknown key raises an error 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 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 the environment variable "CLEVERAGENTS_CORE_SERVER_PORT" is set to "9090" When I resolve config key "core.server_port" Then the resolved value should be integer 9090 Scenario: Boolean value true is coerced from string Given the environment variable "CLEVERAGENTS_CORE_DEBUG_ENABLED" is set to "true" When I resolve config key "core.debug_enabled" Then the resolved value should be boolean true Scenario: Boolean value false is coerced from string Given the environment variable "CLEVERAGENTS_CORE_DEBUG_ENABLED" is set to "false" When I resolve config key "core.debug_enabled" Then the resolved value should be boolean false Scenario: Float value is coerced from string Given the environment variable "CLEVERAGENTS_PROVIDER_TEMPERATURE" is set to "0.9" When I resolve config key "provider.temperature" Then the resolved value should be float 0.9 Scenario: Invalid boolean string raises TypeError When I attempt to validate type for key "core.debug_enabled" with value "notabool" Then the config TypeError message should contain "Cannot convert" Scenario: Invalid integer string raises TypeError When I attempt to validate type for key "core.server_port" with value "notanumber" Then the config TypeError message should contain "Type mismatch" # --- Verbose resolution chain --- Scenario: Verbose mode returns full resolution chain When I resolve config key "core.log_level" with verbose mode Then the resolution chain should have 5 entries And the chain should include source "cli_flag" And the chain should include source "env_var" 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 Then the registry should contain key "core.log_level" And the registry should contain key "core.debug_enabled" And the registry should contain key "core.env" Scenario: Registry contains plan keys Then the registry should contain key "plan.auto_apply" And the registry should contain key "plan.max_retries" And the registry should contain key "plan.timeout_seconds" Scenario: Registry contains provider keys Then the registry should contain key "provider.default_provider" And the registry should contain key "provider.default_model" And the registry should contain key "provider.temperature" Scenario: Registry contains sandbox keys Then the registry should contain key "sandbox.strategy" And the registry should contain key "sandbox.auto_cleanup" And the registry should contain key "sandbox.max_age_hours" Scenario: Registry contains context keys Then the registry should contain key "context.max_files" And the registry should contain key "context.max_tokens" Scenario: Registry contains index keys Then the registry should contain key "index.enabled" And the registry should contain key "index.backend" # --- TOML file management --- Scenario: Writing and reading TOML config roundtrips 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 When I write config data to a new directory Then the config directory should exist Scenario: Non-project-scopable keys ignore project scope Given I have written project "proj" config key "core.database_url" with value "sqlite:///other.db" When I resolve config key "core.database_url" for project "proj" Then the resolved source should be "default" # --- Resolve all --- Scenario: Resolve all returns all registered keys When I resolve all keys Then the result should contain all registered keys # --- Set value --- Scenario: Set value persists to TOML file 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 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 When I get entry for key "nonexistent.key" Then the entry should be None