2005b8ef82
CI / push-validation (push) Successful in 18s
CI / build (push) Successful in 19s
CI / helm (push) Successful in 24s
CI / lint (push) Successful in 29s
CI / security (push) Successful in 1m11s
CI / e2e_tests (push) Successful in 2m56s
CI / quality (push) Successful in 3m40s
CI / typecheck (push) Successful in 3m59s
CI / integration_tests (push) Successful in 4m3s
CI / unit_tests (push) Successful in 4m55s
CI / docker (push) Successful in 10s
CI / coverage (push) Successful in 10m44s
CI / status-check (push) Successful in 1s
CI / benchmark-regression (push) Has been skipped
CI / benchmark-publish (push) Successful in 1h13m28s
## Summary Replaces all 234 bare `@skip` occurrences across 82 Behave feature files with the correct TDD issue-capture tagging system described in CONTRIBUTING.md § Bug Fix Workflow. Previously, the noxfile ran Behave with `--tags=not @skip`, silently excluding all `@skip`-tagged scenarios from every CI run. These tests never ran, never inverted results via the `@tdd_expected_fail` mechanism, and never contributed to coverage — defeating the purpose of TDD issue-capture testing. Every `@skip` occurrence had a commented-out hint line immediately above it showing the intended proper tags (e.g., `# @tdd_issue @tdd_issue_4272 @tdd_expected_fail @skip`), confirming they were all intended for conversion. ## Changes ### Mechanical conversion (234 replacements across 82 files) - Extracted the proper TDD tags from the comment hint above each `@skip` line, removed `@skip` from the tag set, and replaced the `@skip` line with those tags. - Removed the now-redundant comment hint lines alongside each replacement. ### Bug-fixed scenarios — `@tdd_expected_fail` removed (84 scenarios) - After conversion, ran `nox -s unit_tests` to identify which newly-enabled `@tdd_expected_fail` scenarios now **pass** (their referenced bugs have already been fixed). Removed `@tdd_expected_fail` from those 84 scenarios and their corresponding feature-level tags, leaving only the permanent `@tdd_issue @tdd_issue_<N>` regression-guard tags. - Affected features include: `tdd_tool_runner_env_precedence`, `tdd_automation_profile_session_leak`, `tls_certificate_check`, `project_create_persist`, `resource_type_bootstrap_*`, and 18 others. ### Noxfile cleanup - Removed all four `--tags=not @skip` arguments from `noxfile.py` (unit_tests and coverage sessions). With zero `@skip` tags remaining in the codebase, this filter was dead code and its presence would mislead future maintainers into thinking `@skip` is still a supported escape mechanism. ### Regression guard files - Split the regression guards into two focused files: - `tdd_regression_guards_exec_env.feature` for bug #4281 (exec-env precedence) - `tdd_regression_guards_session_list.feature` for bug #4271 (session list summary) - Each file carries only its own `@tdd_issue` tags at the feature level, avoiding cross-contamination via Behave tag inheritance. The `Background` step (`session-list-summary mock`) only appears in the session-list file where it is actually needed. ### Duplicate tag cleanup - Removed duplicate `@tdd_issue @tdd_issue_4287` tag lines in `tdd_skill_add_regression.feature` (lines 20 and 29). ### Inline comment for retained `@tdd_expected_fail` - Added inline comment in `ci_workflow_validation.feature:134` explaining why this specific #4227 scenario retains `@tdd_expected_fail` despite #4227 being closed (CI YAML does not encode threshold as a machine-readable value). ### Known edge cases — `@tdd_expected_fail` retained (closed issues, fix on master, scenarios still fail) The following issues are **closed** and their fixes **are on master**, but the specific test assertions still fail because the fixes address other aspects of the bugs. The `@tdd_expected_fail` tags are functionally correct and must remain until the specific scenario assertions pass: - `tdd_exec_env_resolution_precedence.feature` — bug #1080 (closed 2026-03-31). The precedence-level-2-vs-4 scenario still fails. - `session_list_summary_dedup.feature` — bug #3046 (closed 2026-04-05). The dedup-consistency scenarios still fail. - `actor_add_update_enforcement.feature` — bug #2609 (closed 2026-04-05). The enforcement scenarios still fail. - `ci_workflow_validation.feature:134` — #4227 (closed 2026-04-08). The CI YAML threshold assertion still fails. ## Verification - `grep -r "@skip" features/ --include="*.feature"` → **zero results** ✓ - `grep -n "tags=not @skip" noxfile.py` → **zero results** ✓ - `nox -s unit_tests` → **629 features passed, 0 failed** ✓ (up from ~545 before this PR) - CI all green (coverage ≥ 97%) ✓ - Integration tests (Robot Framework) do not use `@skip` — confirmed no action needed ✓ - E2E tests (Robot Framework) do not use `@skip` — confirmed no action needed ✓ - `CHANGELOG.md` updated with entry for this change ✓ - `CONTRIBUTORS.md` — Rui Hu already listed ✓ ## Issues Addressed Closes #7025 Co-authored-by: CleverThis <hal9000@cleverthis.com> Reviewed-on: #7221 Reviewed-by: HAL 9000 <HAL9000@cleverthis.com> Reviewed-by: HAL9001 <hal9001@cleverthis.com> Co-authored-by: Rui Hu <rui.hu@cleverthis.com> Co-committed-by: Rui Hu <rui.hu@cleverthis.com>
672 lines
27 KiB
Gherkin
672 lines
27 KiB
Gherkin
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 97 percent in noxfile
|
|
Given the noxfile py is loaded for coverage check
|
|
Then the noxfile should contain a fail-under threshold of at least 97
|
|
|
|
|
|
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 97 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 97
|
|
|