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
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:
@@ -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")
|
||||
|
||||
@@ -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"],
|
||||
|
||||
Reference in New Issue
Block a user