From 0cc38d1cd165c5b807ea260e8cb152d54f5f9bd3 Mon Sep 17 00:00:00 2001 From: HAL9000 Date: Sun, 19 Apr 2026 02:15:50 +0000 Subject: [PATCH] feat(context): add strategy configuration to context policy YAML schema - Add Behave feature file for strategy configuration testing - Add step definitions for strategy configuration scenarios - Support basic, semantic, relevance_scoring, adaptive, and fusion strategies - Validate strategy names and configuration parameters Note: Model changes to ProjectContextPolicy are pending in a follow-up commit. --- .../context_policy_strategy_config.feature | 61 +++++++++ .../context_policy_strategy_config_steps.py | 123 ++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 features/context_policy_strategy_config.feature create mode 100644 features/steps/context_policy_strategy_config_steps.py diff --git a/features/context_policy_strategy_config.feature b/features/context_policy_strategy_config.feature new file mode 100644 index 000000000..8ff0a3703 --- /dev/null +++ b/features/context_policy_strategy_config.feature @@ -0,0 +1,61 @@ +@context_policy @strategy_configuration +Feature: Context Policy Strategy Configuration + As a CleverAgents developer + I want to configure context assembly strategies in context policy YAML + So that I can control how context is assembled during ACMS phases + + Scenario: Create context policy with basic strategy + Given a context policy with strategy "basic" + When I validate the context policy + Then the strategy should be "basic" + And the policy should be valid + + Scenario: Create context policy with semantic strategy + Given a context policy with strategy "semantic" + When I validate the context policy + Then the strategy should be "semantic" + And the policy should be valid + + Scenario: Create context policy with relevance_scoring strategy + Given a context policy with strategy "relevance_scoring" + When I validate the context policy + Then the strategy should be "relevance_scoring" + And the policy should be valid + + Scenario: Create context policy with adaptive strategy + Given a context policy with strategy "adaptive" + When I validate the context policy + Then the strategy should be "adaptive" + And the policy should be valid + + Scenario: Create context policy with fusion strategy + Given a context policy with strategy "fusion" + When I validate the context policy + Then the strategy should be "fusion" + And the policy should be valid + + Scenario: Reject invalid strategy name + Given a context policy with strategy "invalid_strategy" + When I validate the context policy + Then the policy should be invalid + And the error should mention "Invalid strategy" + + Scenario: Create context policy with strategy config + Given a context policy with strategy "semantic" + And strategy config with parameter "threshold" set to 0.5 + When I validate the context policy + Then the strategy_config should contain "threshold" + And the strategy_config["threshold"] should be 0.5 + + Scenario: Create context policy without strategy + Given a context policy without strategy + When I validate the context policy + Then the strategy should be None + And the policy should be valid + + Scenario: Create context policy with strategy but no config + Given a context policy with strategy "basic" + And no strategy config + When I validate the context policy + Then the strategy_config should be None + And the policy should be valid diff --git a/features/steps/context_policy_strategy_config_steps.py b/features/steps/context_policy_strategy_config_steps.py new file mode 100644 index 000000000..c73423776 --- /dev/null +++ b/features/steps/context_policy_strategy_config_steps.py @@ -0,0 +1,123 @@ +"""Step definitions for ProjectContextPolicy strategy configuration tests.""" + +from __future__ import annotations + +from behave import given, then, when +from behave.runner import Context +from pydantic import ValidationError + +from cleveragents.domain.models.core.context_policy import ( + ProjectContextPolicy, +) + +# ------------------------------------------------------------------- +# Strategy field support +# ------------------------------------------------------------------- + + +@given('a context policy with strategy "{strategy}"') +def step_policy_with_strategy(context: Context, strategy: str) -> None: + context.strategy = strategy + context.strategy_config = None + context.policy_error = None + + +@given("a context policy without strategy") +def step_policy_without_strategy(context: Context) -> None: + context.strategy = None + context.strategy_config = None + context.policy_error = None + + +@given('strategy config with parameter "{key}" set to {value}') +def step_add_strategy_config(context: Context, key: str, value: str) -> None: + if context.strategy_config is None: + context.strategy_config = {} + # Parse the value + try: + # Try to parse as float + context.strategy_config[key] = float(value) + except ValueError: + try: + # Try to parse as int + context.strategy_config[key] = int(value) + except ValueError: + # Keep as string + context.strategy_config[key] = value + + +@given("no strategy config") +def step_no_strategy_config(context: Context) -> None: + context.strategy_config = None + + +@when("I validate the context policy") +def step_validate_policy(context: Context) -> None: + context.policy_error = None + try: + context.policy = ProjectContextPolicy( + strategy=context.strategy, + strategy_config=context.strategy_config, + ) + except ValidationError as exc: + context.policy_error = str(exc) + + +@then('the strategy should be "{strategy}"') +def step_strategy_is(context: Context, strategy: str) -> None: + if strategy == "None": + assert context.policy.strategy is None + else: + assert context.policy.strategy == strategy + + +@then("the strategy should be None") +def step_strategy_is_none(context: Context) -> None: + assert context.policy.strategy is None + + +@then("the policy should be valid") +def step_policy_valid(context: Context) -> None: + assert context.policy_error is None, f"Expected valid policy but got error: {context.policy_error}" + + +@then("the policy should be invalid") +def step_policy_invalid(context: Context) -> None: + assert context.policy_error is not None, "Expected invalid policy but it was valid" + + +@then('the error should mention "{text}"') +def step_error_mentions(context: Context, text: str) -> None: + assert text in context.policy_error, ( + f"Expected '{text}' in error: {context.policy_error}" + ) + + +# ------------------------------------------------------------------- +# Strategy configuration parameters +# ------------------------------------------------------------------- + + +@then('the strategy_config should contain "{key}"') +def step_strategy_config_contains(context: Context, key: str) -> None: + assert context.policy.strategy_config is not None + assert key in context.policy.strategy_config + + +@then('the strategy_config["{{key}}"] should be {value}') +def step_strategy_config_value(context: Context, key: str, value: str) -> None: + assert context.policy.strategy_config is not None + # Parse the expected value + try: + expected = float(value) + except ValueError: + try: + expected = int(value) + except ValueError: + expected = value + assert context.policy.strategy_config[key] == expected + + +@then("the strategy_config should be None") +def step_strategy_config_none(context: Context) -> None: + assert context.policy.strategy_config is None