fix(context-policy): resolve AmbiguousStep conflict and fix ruff formatting
CI / load-versions (pull_request) Successful in 8s
CI / push-validation (pull_request) Successful in 9s
CI / build (pull_request) Successful in 17s
CI / helm (pull_request) Successful in 18s
CI / lint (pull_request) Successful in 20s
CI / quality (pull_request) Successful in 20s
CI / typecheck (pull_request) Successful in 47s
CI / security (pull_request) Successful in 1m20s
CI / unit_tests (pull_request) Successful in 5m57s
CI / docker (pull_request) Successful in 2m17s
CI / integration_tests (pull_request) Successful in 8m51s
CI / coverage (pull_request) Successful in 11m41s
CI / status-check (pull_request) Successful in 1s

Rename step decorators in context_policy_strategy_config_steps.py from
'the strategy should be "{strategy}"' to 'the policy strategy should be
"{strategy}"' (and likewise for the None variant) to avoid collision with
the identically-patterned step already registered in
plan_merge_strategy_steps.py. Update the feature file to match.

Also apply ruff format to the three files flagged by CI lint gate:
- features/steps/context_policy_strategy_config_steps.py
- scripts/update_context_policy.py
- src/cleveragents/domain/models/core/context_policy.py

ISSUES CLOSED: #7572
This commit is contained in:
2026-06-18 22:42:40 -04:00
committed by drew
parent c104425bed
commit 91d497ca03
4 changed files with 75 additions and 75 deletions
@@ -7,31 +7,31 @@ Feature: Context Policy Strategy Configuration
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"
Then the policy 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"
Then the policy 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"
Then the policy 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"
Then the policy 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"
Then the policy strategy should be "fusion"
And the policy should be valid
Scenario: Reject invalid strategy name
@@ -50,7 +50,7 @@ Feature: Context Policy Strategy Configuration
Scenario: Create context policy without strategy
Given a context policy without strategy
When I validate the context policy
Then the strategy should be None
Then the policy strategy should be None
And the policy should be valid
Scenario: Create context policy with strategy but no config
@@ -63,7 +63,7 @@ def step_validate_policy(context: Context) -> None:
context.policy_error = str(exc)
@then('the strategy should be "{strategy}"')
@then('the policy strategy should be "{strategy}"')
def step_strategy_is(context: Context, strategy: str) -> None:
if strategy == "None":
assert context.policy.strategy is None
@@ -71,14 +71,16 @@ def step_strategy_is(context: Context, strategy: str) -> None:
assert context.policy.strategy == strategy
@then("the strategy should be None")
@then("the policy 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}"
assert context.policy_error is None, (
f"Expected valid policy but got error: {context.policy_error}"
)
@then("the policy should be invalid")
+55 -59
View File
@@ -5,62 +5,61 @@ import sys
from pathlib import Path
# Read the file
policy_file = Path('src/cleveragents/domain/models/core/context_policy.py')
policy_file = Path("src/cleveragents/domain/models/core/context_policy.py")
content = policy_file.read_text()
# Update the imports to include Any
content = content.replace(
'from typing import TYPE_CHECKING',
'from typing import TYPE_CHECKING, Any'
"from typing import TYPE_CHECKING", "from typing import TYPE_CHECKING, Any"
)
# Add VALID_STRATEGIES constant after VALID_PHASES
old_phases = (
'VALID_PHASES: frozenset[str] = frozenset('
"VALID_PHASES: frozenset[str] = frozenset("
'{"default", "strategize", "execute", "apply"})'
)
new_phases = (
'VALID_PHASES: frozenset[str] = frozenset('
"VALID_PHASES: frozenset[str] = frozenset("
'{"default", "strategize", "execute", "apply"})\n\n'
'VALID_STRATEGIES: frozenset[str] = frozenset({\n'
"VALID_STRATEGIES: frozenset[str] = frozenset({\n"
' "basic",\n'
' "semantic",\n'
' "relevance_scoring",\n'
' "adaptive",\n'
' "fusion",\n'
'})'
"})"
)
content = content.replace(old_phases, new_phases)
# Update the docstring for ProjectContextPolicy to mention strategy
old_docstring = (
'class ProjectContextPolicy(BaseModel):\n'
"class ProjectContextPolicy(BaseModel):\n"
' """Controls what context is available during each ACMS phase.\n'
'\n'
' Uses view inheritance: ``default`` → ``strategize`` →\n'
' ``execute`` → ``apply``. Each phase can override or inherit\n'
' from its parent.\n'
'\n'
' An empty ``ProjectContextPolicy()`` defaults to including\n'
' everything (the ``default_view`` has empty include lists which\n'
"\n"
" Uses view inheritance: ``default`` → ``strategize`` →\n"
" ``execute`` → ``apply``. Each phase can override or inherit\n"
" from its parent.\n"
"\n"
" An empty ``ProjectContextPolicy()`` defaults to including\n"
" everything (the ``default_view`` has empty include lists which\n"
' means "all").\n'
' """'
)
new_docstring = (
'class ProjectContextPolicy(BaseModel):\n'
"class ProjectContextPolicy(BaseModel):\n"
' """Controls what context is available during each ACMS phase.\n'
'\n'
' Uses view inheritance: ``default`` → ``strategize`` →\n'
' ``execute`` → ``apply``. Each phase can override or inherit\n'
' from its parent.\n'
'\n'
' An empty ``ProjectContextPolicy()`` defaults to including\n'
' everything (the ``default_view`` has empty include lists which\n'
"\n"
" Uses view inheritance: ``default`` → ``strategize`` →\n"
" ``execute`` → ``apply``. Each phase can override or inherit\n"
" from its parent.\n"
"\n"
" An empty ``ProjectContextPolicy()`` defaults to including\n"
" everything (the ``default_view`` has empty include lists which\n"
' means "all").\n'
'\n'
' Optionally specifies a context assembly strategy and its\n'
' configuration parameters.\n'
"\n"
" Optionally specifies a context assembly strategy and its\n"
" configuration parameters.\n"
' """'
)
@@ -68,50 +67,47 @@ content = content.replace(old_docstring, new_docstring)
# Add strategy and strategy_config fields before the resolve_view method
old_fields = (
' apply_view: ContextView | None = Field(\n'
' default=None,\n'
" apply_view: ContextView | None = Field(\n"
" default=None,\n"
' description=("Overrides for Apply (inherits from execute if None)"),\n'
' )\n'
'\n'
' def resolve_view(self, phase: str) -> ContextView:'
" )\n"
"\n"
" def resolve_view(self, phase: str) -> ContextView:"
)
error_msg = (
'f"Invalid strategy \'{v}\': must be one of '
'{sorted(VALID_STRATEGIES)}"'
)
error_msg = "f\"Invalid strategy '{v}': must be one of {sorted(VALID_STRATEGIES)}\""
new_fields = (
' apply_view: ContextView | None = Field(\n'
' default=None,\n'
" apply_view: ContextView | None = Field(\n"
" default=None,\n"
' description=("Overrides for Apply (inherits from execute if None)"),\n'
' )\n'
' strategy: str | None = Field(\n'
' default=None,\n'
' description=(\n'
" )\n"
" strategy: str | None = Field(\n"
" default=None,\n"
" description=(\n"
' "Context assembly strategy name. "\n'
' "Valid values: basic, semantic, relevance_scoring, adaptive, fusion"\n'
' ),\n'
' )\n'
' strategy_config: dict[str, Any] | None = Field(\n'
' default=None,\n'
" ),\n"
" )\n"
" strategy_config: dict[str, Any] | None = Field(\n"
" default=None,\n"
' description="Strategy-specific configuration parameters",\n'
' )\n'
'\n'
" )\n"
"\n"
' @field_validator("strategy")\n'
' @classmethod\n'
' def _validate_strategy(\n'
' cls: type[ProjectContextPolicy],\n'
' v: str | None,\n'
' ) -> str | None:\n'
" @classmethod\n"
" def _validate_strategy(\n"
" cls: type[ProjectContextPolicy],\n"
" v: str | None,\n"
" ) -> str | None:\n"
' """Validate that strategy name is in the list of valid strategies."""\n'
' if v is not None and v not in VALID_STRATEGIES:\n'
' raise ValueError(\n'
' ' + error_msg + '\n'
' )\n'
' return v\n'
'\n'
' def resolve_view(self, phase: str) -> ContextView:'
" if v is not None and v not in VALID_STRATEGIES:\n"
" raise ValueError(\n"
" " + error_msg + "\n"
" )\n"
" return v\n"
"\n"
" def resolve_view(self, phase: str) -> ContextView:"
)
content = content.replace(old_fields, new_fields)
@@ -47,13 +47,15 @@ if TYPE_CHECKING:
VALID_PHASES: frozenset[str] = frozenset({"default", "strategize", "execute", "apply"})
VALID_STRATEGIES: frozenset[str] = frozenset({
"basic",
"semantic",
"relevance_scoring",
"adaptive",
"fusion",
})
VALID_STRATEGIES: frozenset[str] = frozenset(
{
"basic",
"semantic",
"relevance_scoring",
"adaptive",
"fusion",
}
)
_INHERITANCE_CHAIN: dict[str, list[str]] = {
"default": ["default"],