Files
cleveragents-core/features/steps/sliding_window_strategy_steps.py
T
HAL9000 c91a6a252d
CI / lint (pull_request) Successful in 38s
CI / build (pull_request) Successful in 58s
CI / quality (pull_request) Successful in 1m18s
CI / typecheck (pull_request) Successful in 1m18s
CI / security (pull_request) Successful in 1m34s
CI / helm (pull_request) Successful in 54s
CI / push-validation (pull_request) Successful in 29s
CI / unit_tests (pull_request) Successful in 5m39s
CI / docker (pull_request) Successful in 1m37s
CI / integration_tests (pull_request) Successful in 9m40s
CI / coverage (pull_request) Successful in 12m19s
CI / status-check (pull_request) Successful in 4s
style(context): apply ruff formatting to SlidingWindowStrategy and step definitions
Applied ruff format to sliding_window_strategy.py and
sliding_window_strategy_steps.py to fix CI lint format check failure.

ISSUES CLOSED: #9995
2026-06-06 11:27:30 -04:00

257 lines
8.5 KiB
Python

"""Step definitions for ``features/sliding_window_strategy.feature``.
Covers the SlidingWindowStrategy:
* Protocol conformance
* Messages mode truncation
* Tokens mode truncation
* System prompt preservation
* Budget enforcement
* can_handle confidence
* Plugin registry registration
* Configuration validation
"""
from __future__ import annotations
from typing import Any
from behave import given, then, when
from behave.runner import Context
from cleveragents.application.services.acms_service import (
ACMSPipeline,
ContextStrategy,
)
from cleveragents.application.services.sliding_window_strategy import (
SlidingWindowStrategy,
)
from cleveragents.domain.models.core.context_fragment import (
ContextBudget,
ContextFragment,
FragmentProvenance,
)
__all__: list[str] = []
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
def _make_sw_fragment(
uko_node: str,
content: str,
score: float,
tokens: int,
depth: int,
role: str = "user",
) -> ContextFragment:
"""Build a ``ContextFragment`` for sliding window tests."""
metadata: dict[str, str] = {}
if role:
metadata["role"] = role
return ContextFragment(
uko_node=uko_node,
content=content,
relevance_score=score,
token_count=tokens,
detail_depth=depth,
provenance=FragmentProvenance(resource_uri=uko_node),
metadata=metadata,
)
# ---------------------------------------------------------------------------
# Given steps
# ---------------------------------------------------------------------------
@given('a SlidingWindowStrategy with window_size {size:d} and window_mode "{mode}"')
def step_sliding_window_strategy(context: Context, size: int, mode: str) -> None:
context.sw_strategy = SlidingWindowStrategy(
window_size=size,
window_mode=mode, # type: ignore[arg-type]
)
@given("the following sliding window fragments:")
def step_sw_fragments_table(context: Context) -> None:
context.sw_fragments = []
for row in context.table:
role = row["role"] if "role" in row.headings else "user"
frag = _make_sw_fragment(
uko_node=row["uko_node"],
content=row["content"],
score=float(row["score"]),
tokens=int(row["tokens"]),
depth=int(row["depth"]),
role=role,
)
context.sw_fragments.append(frag)
@given("an empty sliding window fragment list")
def step_sw_empty_fragments(context: Context) -> None:
context.sw_fragments = []
@given(
"a sliding window budget with max_tokens {max_tokens:d} and reserved_tokens {reserved:d}"
)
def step_sw_budget(context: Context, max_tokens: int, reserved: int) -> None:
context.sw_budget = ContextBudget(max_tokens=max_tokens, reserved_tokens=reserved)
@given("an ACMS pipeline for sliding window tests")
def step_sw_pipeline(context: Context) -> None:
# Create the pipeline and register SlidingWindowStrategy under "sliding_window".
# This satisfies the requirement to register the strategy in the plugin
# registry under key "sliding_window".
pipeline = ACMSPipeline()
pipeline.register_strategy("sliding_window", SlidingWindowStrategy())
context.sw_pipeline = pipeline
# ---------------------------------------------------------------------------
# When steps
# ---------------------------------------------------------------------------
@when("I apply the SlidingWindowStrategy")
def step_apply_sw(context: Context) -> None:
context.sw_result = list(
context.sw_strategy.assemble(context.sw_fragments, context.sw_budget)
)
@when("I check can_handle on SlidingWindowStrategy")
def step_sw_can_handle(context: Context) -> None:
request: dict[str, Any] = {}
context.sw_confidence = context.sw_strategy.can_handle(request)
@when("I register a custom SlidingWindowStrategy with the pipeline")
def step_register_custom_sw(context: Context) -> None:
custom_strategy = SlidingWindowStrategy(window_size=50, window_mode="messages")
context.sw_pipeline.register_strategy("custom_sliding_window", custom_strategy)
@when("I attempt to create a SlidingWindowStrategy with window_size {size:d}")
def step_attempt_create_sw_bad_size(context: Context, size: int) -> None:
context.sw_error = None
try:
SlidingWindowStrategy(window_size=size, window_mode="messages")
except ValueError as exc:
context.sw_error = exc
@when('I attempt to create a SlidingWindowStrategy with window_mode "{mode}"')
def step_attempt_create_sw_bad_mode(context: Context, mode: str) -> None:
context.sw_error = None
try:
SlidingWindowStrategy(window_size=10, window_mode=mode) # type: ignore[arg-type]
except ValueError as exc:
context.sw_error = exc
@when(
'I create a SlidingWindowStrategy with window_size {size:d} and window_mode "{mode}"'
)
def step_create_sw_valid(context: Context, size: int, mode: str) -> None:
context.sw_error = None
try:
context.sw_strategy = SlidingWindowStrategy(
window_size=size,
window_mode=mode, # type: ignore[arg-type]
)
except ValueError as exc:
context.sw_error = exc
# ---------------------------------------------------------------------------
# Then steps
# ---------------------------------------------------------------------------
@then("the sw strategy should satisfy the ContextStrategy protocol")
def step_sw_satisfies_protocol(context: Context) -> None:
assert isinstance(context.sw_strategy, ContextStrategy), (
f"SlidingWindowStrategy does not satisfy ContextStrategy protocol: "
f"{type(context.sw_strategy)}"
)
@then('the sw strategy name should be "sliding_window"')
def step_sw_name_sliding_window(context: Context) -> None:
actual = context.sw_strategy.name
assert actual == "sliding_window", f"Expected name 'sliding_window', got '{actual}'"
@then("the sw strategy should have a capabilities object")
def step_sw_has_capabilities(context: Context) -> None:
caps = context.sw_strategy.capabilities
assert caps is not None, "Expected capabilities object, got None"
@then('the sw strategy explain should contain "{text}"')
def step_sw_explain_contains(context: Context, text: str) -> None:
explanation = context.sw_strategy.explain()
assert text.lower() in explanation.lower(), (
f"Expected explain to contain '{text}', got: {explanation}"
)
@then("{count:d} fragments should be returned by sliding window strategy")
def step_sw_fragment_count(context: Context, count: int) -> None:
actual = len(context.sw_result)
assert actual == count, (
f"Expected {count} fragments from sliding window, got {actual}. "
f"Fragments: {[f.uko_node for f in context.sw_result]}"
)
@then('the sliding window result should contain uko_node "{uko_node}"')
def step_sw_result_contains(context: Context, uko_node: str) -> None:
nodes = [f.uko_node for f in context.sw_result]
assert uko_node in nodes, f"Expected uko_node '{uko_node}' in result, got: {nodes}"
@then('the sliding window result should not contain uko_node "{uko_node}"')
def step_sw_result_not_contains(context: Context, uko_node: str) -> None:
nodes = [f.uko_node for f in context.sw_result]
assert uko_node not in nodes, (
f"Expected uko_node '{uko_node}' NOT in result, but it was. Nodes: {nodes}"
)
@then("the sliding window confidence should be greater than 0.0")
def step_sw_confidence_positive(context: Context) -> None:
actual = context.sw_confidence
assert actual > 0.0, f"Expected confidence > 0.0, got {actual}"
@then('the sw pipeline should have strategy "{name}"')
def step_sw_pipeline_has_strategy(context: Context, name: str) -> None:
registered = context.sw_pipeline._strategies
assert name in registered, (
f"Pipeline does not have strategy '{name}'. "
f"Registered: {list(registered.keys())}"
)
@then("a ValueError should be raised for sliding window")
def step_sw_value_error_raised(context: Context) -> None:
assert context.sw_error is not None, (
"Expected a ValueError to be raised, but no error was raised"
)
assert isinstance(context.sw_error, ValueError), (
f"Expected ValueError, got {type(context.sw_error)}: {context.sw_error}"
)
@then("no error should be raised for sliding window")
def step_sw_no_error(context: Context) -> None:
assert context.sw_error is None, f"Expected no error, but got: {context.sw_error}"