forked from HAL9000/cleveragents-core
31472b5413
Add Behave feature/step pairs that exercise uncovered branches across handlers, LSP, CLI, and service layers to reach the coverage gate. ISSUES CLOSED: #1232
940 lines
35 KiB
Python
940 lines
35 KiB
Python
"""Step definitions for execute_phase_context_assembler_coverage.feature.
|
|
|
|
Exercises all uncovered lines in
|
|
``cleveragents.application.services.execute_phase_context_assembler``:
|
|
- ExecutePhaseContextAssembler protocol stub (line 36)
|
|
- _resolve_execute_view success and exception paths (lines 57-66)
|
|
- _path_matches static method (lines 71-75)
|
|
- _resource_matches static method (lines 83-89)
|
|
- _to_context_fragment conversion (lines 99-117)
|
|
- assemble() method: filtering, logging, pipeline call (lines 122-240)
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
from behave import given, then, when
|
|
from behave.runner import Context
|
|
|
|
from cleveragents.application.services.execute_phase_context_assembler import (
|
|
ACMSExecutePhaseContextAssembler,
|
|
)
|
|
from cleveragents.domain.models.acms.crp import AssembledContext
|
|
from cleveragents.domain.models.acms.tiers import TieredFragment
|
|
from cleveragents.domain.models.core.context_policy import (
|
|
ContextView,
|
|
ProjectContextPolicy,
|
|
)
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Helpers
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
def _make_tiered_fragment(
|
|
*,
|
|
fragment_id: str = "frag-001",
|
|
content: str = "hello world",
|
|
resource_id: str = "res:test",
|
|
project_name: str = "proj-alpha",
|
|
token_count: int = 5,
|
|
metadata: dict[str, Any] | None = None,
|
|
) -> TieredFragment:
|
|
"""Build a TieredFragment for testing."""
|
|
return TieredFragment(
|
|
fragment_id=fragment_id,
|
|
content=content,
|
|
resource_id=resource_id,
|
|
project_name=project_name,
|
|
token_count=token_count,
|
|
metadata=metadata if metadata is not None else {},
|
|
)
|
|
|
|
|
|
def _make_plan(
|
|
*,
|
|
plan_id: str = "01ARZ3NDEKTSV4RRFFQ69G5FAV",
|
|
project_names: list[str] | None = None,
|
|
) -> MagicMock:
|
|
"""Build a mock plan with project_links."""
|
|
plan = MagicMock()
|
|
plan.identity.plan_id = plan_id
|
|
if project_names is None:
|
|
plan.project_links = []
|
|
else:
|
|
links = []
|
|
for name in project_names:
|
|
link = MagicMock()
|
|
link.project_name = name
|
|
links.append(link)
|
|
plan.project_links = links
|
|
return plan
|
|
|
|
|
|
def _make_pipeline_result() -> MagicMock:
|
|
"""Build a standard mock pipeline result."""
|
|
pr = MagicMock()
|
|
pr.fragments = ()
|
|
pr.total_tokens = 5
|
|
pr.budget_used = 0.1
|
|
pr.strategies_used = ("relevance",)
|
|
pr.context_hash = "hash123"
|
|
pr.preamble = None
|
|
pr.provenance_map = {}
|
|
return pr
|
|
|
|
|
|
def _make_assembler(
|
|
*,
|
|
policy: ProjectContextPolicy | None = None,
|
|
policy_exception: bool = False,
|
|
scoped_fragments: list[TieredFragment] | None = None,
|
|
pipeline_result: MagicMock | None = None,
|
|
) -> ACMSExecutePhaseContextAssembler:
|
|
"""Build an ACMSExecutePhaseContextAssembler with mocked dependencies."""
|
|
tier_service = MagicMock()
|
|
if scoped_fragments is not None:
|
|
tier_service.get_scoped_view.return_value = scoped_fragments
|
|
else:
|
|
tier_service.get_scoped_view.return_value = []
|
|
|
|
repo = MagicMock()
|
|
if policy_exception:
|
|
repo.get_context_policy.side_effect = RuntimeError("db error")
|
|
elif policy is not None:
|
|
repo.get_context_policy.return_value = policy
|
|
else:
|
|
repo.get_context_policy.return_value = ProjectContextPolicy()
|
|
|
|
mock_pipeline = MagicMock()
|
|
if pipeline_result is not None:
|
|
mock_pipeline.assemble.return_value = pipeline_result
|
|
else:
|
|
mock_pipeline.assemble.return_value = _make_pipeline_result()
|
|
|
|
assembler = ACMSExecutePhaseContextAssembler(
|
|
context_tier_service=tier_service,
|
|
project_repository=repo,
|
|
acms_pipeline=mock_pipeline,
|
|
hot_max_tokens=4096,
|
|
)
|
|
return assembler
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Protocol (line 36)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@given("epcov a class implementing the ExecutePhaseContextAssembler protocol")
|
|
def step_epcov_protocol_stub(context: Context) -> None:
|
|
|
|
class Stub:
|
|
def assemble(self, plan: Any) -> AssembledContext | None:
|
|
return None
|
|
|
|
context.epcov_protocol_stub = Stub()
|
|
|
|
|
|
@when("epcov I call assemble on the protocol stub")
|
|
def step_epcov_call_protocol_assemble(context: Context) -> None:
|
|
context.epcov_protocol_result = context.epcov_protocol_stub.assemble(None)
|
|
|
|
|
|
@then("epcov the result should be None")
|
|
def step_epcov_protocol_result_none(context: Context) -> None:
|
|
assert context.epcov_protocol_result is None
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# _resolve_execute_view (lines 57-66)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@given("epcov an assembler with a project repository returning a custom policy")
|
|
def step_epcov_assembler_custom_policy(context: Context) -> None:
|
|
custom_view = ContextView(include_resources=["custom:*"])
|
|
policy = ProjectContextPolicy(execute_view=custom_view)
|
|
context.epcov_assembler = _make_assembler(policy=policy)
|
|
|
|
|
|
@when('epcov I resolve the execute view for "{project_name}"')
|
|
def step_epcov_resolve_execute_view(context: Context, project_name: str) -> None:
|
|
context.epcov_resolved_view = context.epcov_assembler._resolve_execute_view(
|
|
project_name
|
|
)
|
|
|
|
|
|
@then("epcov the resolved view should have the custom include_resources")
|
|
def step_epcov_resolved_view_custom(context: Context) -> None:
|
|
view = context.epcov_resolved_view
|
|
assert view.include_resources == ["custom:*"], (
|
|
f"Expected ['custom:*'], got {view.include_resources}"
|
|
)
|
|
|
|
|
|
@given("epcov an assembler with a project repository that raises an exception")
|
|
def step_epcov_assembler_exception_policy(context: Context) -> None:
|
|
context.epcov_assembler = _make_assembler(policy_exception=True)
|
|
|
|
|
|
@then("epcov the resolved view should be the default empty ContextView")
|
|
def step_epcov_resolved_view_default(context: Context) -> None:
|
|
view = context.epcov_resolved_view
|
|
assert view.include_resources == [], (
|
|
f"Expected empty include_resources, got {view.include_resources}"
|
|
)
|
|
assert view.exclude_resources == [], (
|
|
f"Expected empty exclude_resources, got {view.exclude_resources}"
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# _path_matches (lines 71-75)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@when('epcov I check path matching for "{path}" with no include or exclude')
|
|
def step_epcov_path_matches_no_rules(context: Context, path: str) -> None:
|
|
context.epcov_path_result = ACMSExecutePhaseContextAssembler._path_matches(
|
|
path, [], []
|
|
)
|
|
|
|
|
|
@when('epcov I check path matching for "{path}" with include "{pattern}"')
|
|
def step_epcov_path_matches_include(context: Context, path: str, pattern: str) -> None:
|
|
context.epcov_path_result = ACMSExecutePhaseContextAssembler._path_matches(
|
|
path, [pattern], []
|
|
)
|
|
|
|
|
|
@when('epcov I check path matching for "{path}" with exclude "{pattern}"')
|
|
def step_epcov_path_matches_exclude(context: Context, path: str, pattern: str) -> None:
|
|
context.epcov_path_result = ACMSExecutePhaseContextAssembler._path_matches(
|
|
path, [], [pattern]
|
|
)
|
|
|
|
|
|
@then("epcov the path should match")
|
|
def step_epcov_path_should_match(context: Context) -> None:
|
|
assert context.epcov_path_result is True, "Expected path to match"
|
|
|
|
|
|
@then("epcov the path should not match")
|
|
def step_epcov_path_should_not_match(context: Context) -> None:
|
|
assert context.epcov_path_result is False, "Expected path to not match"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# _resource_matches (lines 83-89)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@when('epcov I check resource matching for "{rid}" with no include or exclude')
|
|
def step_epcov_resource_matches_no_rules(context: Context, rid: str) -> None:
|
|
context.epcov_resource_result = ACMSExecutePhaseContextAssembler._resource_matches(
|
|
rid, [], []
|
|
)
|
|
|
|
|
|
@when('epcov I check resource matching for "{rid}" with include "{pattern}"')
|
|
def step_epcov_resource_matches_include(
|
|
context: Context, rid: str, pattern: str
|
|
) -> None:
|
|
context.epcov_resource_result = ACMSExecutePhaseContextAssembler._resource_matches(
|
|
rid, [pattern], []
|
|
)
|
|
|
|
|
|
@when('epcov I check resource matching for "{rid}" with exclude "{pattern}"')
|
|
def step_epcov_resource_matches_exclude(
|
|
context: Context, rid: str, pattern: str
|
|
) -> None:
|
|
context.epcov_resource_result = ACMSExecutePhaseContextAssembler._resource_matches(
|
|
rid, [], [pattern]
|
|
)
|
|
|
|
|
|
@then("epcov the resource should match")
|
|
def step_epcov_resource_should_match(context: Context) -> None:
|
|
assert context.epcov_resource_result is True, "Expected resource to match"
|
|
|
|
|
|
@then("epcov the resource should not match")
|
|
def step_epcov_resource_should_not_match(context: Context) -> None:
|
|
assert context.epcov_resource_result is False, "Expected resource to not match"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# _to_context_fragment (lines 99-117)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@given("epcov an assembler instance")
|
|
def step_epcov_assembler_instance(context: Context) -> None:
|
|
context.epcov_assembler = _make_assembler()
|
|
|
|
|
|
@when("epcov I convert a tiered fragment with detail_depth 3 and relevance 0.8")
|
|
def step_epcov_convert_fragment_full(context: Context) -> None:
|
|
"""Test with int/float metadata values.
|
|
|
|
CoreContextFragment.metadata requires dict[str, str], so non-string
|
|
values will fail validation. We patch CoreContextFragment to accept
|
|
arbitrary kwargs, exercising lines 99-117 including the isinstance
|
|
checks on lines 100-104.
|
|
"""
|
|
import cleveragents.application.services.execute_phase_context_assembler as asm_mod
|
|
|
|
class MockCoreFragment:
|
|
def __init__(self, **kwargs: Any) -> None:
|
|
for k, v in kwargs.items():
|
|
setattr(self, k, v)
|
|
|
|
patcher = patch.object(asm_mod, "CoreContextFragment", MockCoreFragment)
|
|
patcher.start()
|
|
context.add_cleanup(patcher.stop)
|
|
|
|
frag = _make_tiered_fragment(
|
|
metadata={"detail_depth": 3, "relevance_score": 0.8, "path": "src/main.py"}
|
|
)
|
|
context.epcov_core_frag = context.epcov_assembler._to_context_fragment(
|
|
frag, strategy="test_strategy"
|
|
)
|
|
|
|
|
|
@then("epcov the core fragment should have detail_depth 3 and relevance 0.8")
|
|
def step_epcov_core_frag_full(context: Context) -> None:
|
|
frag = context.epcov_core_frag
|
|
assert frag.detail_depth == 3, f"Expected detail_depth 3, got {frag.detail_depth}"
|
|
assert frag.relevance_score == 0.8, (
|
|
f"Expected relevance 0.8, got {frag.relevance_score}"
|
|
)
|
|
|
|
|
|
@when("epcov I convert a tiered fragment with no detail_depth or relevance")
|
|
def step_epcov_convert_fragment_defaults(context: Context) -> None:
|
|
"""Test with string-only metadata (no detail_depth or relevance keys)."""
|
|
frag = _make_tiered_fragment(metadata={"path": "src/test.py"})
|
|
context.epcov_core_frag = context.epcov_assembler._to_context_fragment(
|
|
frag, strategy="test_strategy"
|
|
)
|
|
|
|
|
|
@then("epcov the core fragment should have detail_depth 1 and relevance 0.5")
|
|
def step_epcov_core_frag_defaults(context: Context) -> None:
|
|
frag = context.epcov_core_frag
|
|
assert frag.detail_depth == 1, f"Expected detail_depth 1, got {frag.detail_depth}"
|
|
assert frag.relevance_score == 0.5, (
|
|
f"Expected relevance 0.5, got {frag.relevance_score}"
|
|
)
|
|
|
|
|
|
@when('epcov I convert a tiered fragment with detail_depth "high" and relevance "bad"')
|
|
def step_epcov_convert_fragment_non_numeric(context: Context) -> None:
|
|
"""detail_depth='high' and relevance_score='bad' are strings, so they
|
|
fall through to defaults (line 101 else, line 103 else)."""
|
|
frag = _make_tiered_fragment(
|
|
metadata={"detail_depth": "high", "relevance_score": "bad", "path": "x.py"}
|
|
)
|
|
context.epcov_core_frag = context.epcov_assembler._to_context_fragment(
|
|
frag, strategy="test_strategy"
|
|
)
|
|
|
|
|
|
@when("epcov I convert a tiered fragment with relevance 1.5")
|
|
def step_epcov_convert_fragment_high_relevance(context: Context) -> None:
|
|
"""Relevance 1.5 exercises the clamping at line 104: min(1.0, max(0.0, 1.5))."""
|
|
import cleveragents.application.services.execute_phase_context_assembler as asm_mod
|
|
|
|
class MockCoreFragment:
|
|
def __init__(self, **kwargs: Any) -> None:
|
|
for k, v in kwargs.items():
|
|
setattr(self, k, v)
|
|
|
|
patcher = patch.object(asm_mod, "CoreContextFragment", MockCoreFragment)
|
|
patcher.start()
|
|
context.add_cleanup(patcher.stop)
|
|
|
|
frag = _make_tiered_fragment(metadata={"relevance_score": 1.5, "path": "a.py"})
|
|
context.epcov_core_frag = context.epcov_assembler._to_context_fragment(
|
|
frag, strategy="test_strategy"
|
|
)
|
|
|
|
|
|
@then("epcov the core fragment should have clamped relevance 1.0")
|
|
def step_epcov_core_frag_clamped_high(context: Context) -> None:
|
|
frag = context.epcov_core_frag
|
|
assert frag.relevance_score == 1.0, (
|
|
f"Expected clamped relevance 1.0, got {frag.relevance_score}"
|
|
)
|
|
|
|
|
|
@when("epcov I convert a tiered fragment with relevance -0.3")
|
|
def step_epcov_convert_fragment_neg_relevance(context: Context) -> None:
|
|
"""Relevance -0.3 exercises clamping at line 104: min(1.0, max(0.0, -0.3))."""
|
|
import cleveragents.application.services.execute_phase_context_assembler as asm_mod
|
|
|
|
class MockCoreFragment:
|
|
def __init__(self, **kwargs: Any) -> None:
|
|
for k, v in kwargs.items():
|
|
setattr(self, k, v)
|
|
|
|
patcher = patch.object(asm_mod, "CoreContextFragment", MockCoreFragment)
|
|
patcher.start()
|
|
context.add_cleanup(patcher.stop)
|
|
|
|
frag = _make_tiered_fragment(metadata={"relevance_score": -0.3, "path": "a.py"})
|
|
context.epcov_core_frag = context.epcov_assembler._to_context_fragment(
|
|
frag, strategy="test_strategy"
|
|
)
|
|
|
|
|
|
@then("epcov the core fragment should have clamped relevance 0.0")
|
|
def step_epcov_core_frag_clamped_low(context: Context) -> None:
|
|
frag = context.epcov_core_frag
|
|
assert frag.relevance_score == 0.0, (
|
|
f"Expected clamped relevance 0.0, got {frag.relevance_score}"
|
|
)
|
|
|
|
|
|
@when("epcov I convert a tiered fragment with empty resource_id")
|
|
def step_epcov_convert_fragment_no_resource_id(context: Context) -> None:
|
|
"""Empty resource_id triggers the 'uko:' fallback on line 107."""
|
|
import cleveragents.application.services.execute_phase_context_assembler as asm_mod
|
|
|
|
class MockCoreFragment:
|
|
def __init__(self, **kwargs: Any) -> None:
|
|
for k, v in kwargs.items():
|
|
setattr(self, k, v)
|
|
|
|
patcher = patch.object(asm_mod, "CoreContextFragment", MockCoreFragment)
|
|
patcher.start()
|
|
context.add_cleanup(patcher.stop)
|
|
|
|
frag = _make_tiered_fragment(resource_id="", metadata={"path": "a.py"})
|
|
context.epcov_core_frag = context.epcov_assembler._to_context_fragment(
|
|
frag, strategy="test_strategy"
|
|
)
|
|
|
|
|
|
@then('epcov the core fragment uko_node should start with "uko:"')
|
|
def step_epcov_core_frag_uko_fallback(context: Context) -> None:
|
|
frag = context.epcov_core_frag
|
|
assert frag.uko_node.startswith("uko:"), (
|
|
f"Expected uko_node starting with 'uko:', got {frag.uko_node}"
|
|
)
|
|
assert frag.provenance.resource_uri == "unknown", (
|
|
f"Expected provenance resource_uri 'unknown', got {frag.provenance.resource_uri}"
|
|
)
|
|
|
|
|
|
@when('epcov I convert a tiered fragment with path "src/main.py" in metadata')
|
|
def step_epcov_convert_fragment_with_path(context: Context) -> None:
|
|
frag = _make_tiered_fragment(metadata={"path": "src/main.py"})
|
|
context.epcov_core_frag = context.epcov_assembler._to_context_fragment(
|
|
frag, strategy="test_strategy"
|
|
)
|
|
|
|
|
|
@then('epcov the core fragment provenance location should be "src/main.py"')
|
|
def step_epcov_core_frag_provenance_path(context: Context) -> None:
|
|
frag = context.epcov_core_frag
|
|
assert frag.provenance.location == "src/main.py", (
|
|
f"Expected 'src/main.py', got {frag.provenance.location}"
|
|
)
|
|
|
|
|
|
@when("epcov I convert a tiered fragment with non-string path in metadata")
|
|
def step_epcov_convert_fragment_nonstring_path(context: Context) -> None:
|
|
"""Non-string path triggers the isinstance check on line 114."""
|
|
import cleveragents.application.services.execute_phase_context_assembler as asm_mod
|
|
|
|
class MockCoreFragment:
|
|
def __init__(self, **kwargs: Any) -> None:
|
|
for k, v in kwargs.items():
|
|
setattr(self, k, v)
|
|
|
|
class MockProvenance:
|
|
def __init__(self, **kwargs: Any) -> None:
|
|
for k, v in kwargs.items():
|
|
setattr(self, k, v)
|
|
|
|
patcher_cf = patch.object(asm_mod, "CoreContextFragment", MockCoreFragment)
|
|
patcher_prov = patch.object(asm_mod, "CoreFragmentProvenance", MockProvenance)
|
|
patcher_cf.start()
|
|
patcher_prov.start()
|
|
context.add_cleanup(patcher_cf.stop)
|
|
context.add_cleanup(patcher_prov.stop)
|
|
|
|
frag = _make_tiered_fragment(metadata={"path": 12345})
|
|
context.epcov_core_frag = context.epcov_assembler._to_context_fragment(
|
|
frag, strategy="test_strategy"
|
|
)
|
|
|
|
|
|
@then("epcov the core fragment provenance location should be empty")
|
|
def step_epcov_core_frag_provenance_empty(context: Context) -> None:
|
|
frag = context.epcov_core_frag
|
|
assert frag.provenance.location == "", (
|
|
f"Expected empty location, got {frag.provenance.location}"
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# assemble: no project links (lines 122-126)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@given("epcov a plan with no project links")
|
|
def step_epcov_plan_no_links(context: Context) -> None:
|
|
context.epcov_plan = _make_plan(project_names=None)
|
|
|
|
|
|
@when("epcov I call assemble on the plan")
|
|
def step_epcov_call_assemble(context: Context) -> None:
|
|
context.epcov_error = None
|
|
try:
|
|
context.epcov_assembled = context.epcov_assembler.assemble(context.epcov_plan)
|
|
except Exception as exc:
|
|
context.epcov_error = exc
|
|
context.epcov_assembled = None
|
|
|
|
|
|
@then("epcov the assembled result should be None")
|
|
def step_epcov_assembled_none(context: Context) -> None:
|
|
if context.epcov_error is not None:
|
|
raise AssertionError(f"Unexpected error: {context.epcov_error}")
|
|
assert context.epcov_assembled is None, (
|
|
f"Expected None, got {context.epcov_assembled}"
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# assemble: empty scoped view (lines 128-131)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@given("epcov an assembler with scoped view returning empty list")
|
|
def step_epcov_assembler_empty_scoped(context: Context) -> None:
|
|
context.epcov_assembler = _make_assembler(scoped_fragments=[])
|
|
|
|
|
|
@given("epcov a plan with project links")
|
|
def step_epcov_plan_with_links(context: Context) -> None:
|
|
context.epcov_plan = _make_plan(project_names=["proj-alpha"])
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# assemble: fragment excluded by missing view (lines 140-144)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@given('epcov an assembler with views only for "proj-alpha"')
|
|
def step_epcov_assembler_views_only_alpha(context: Context) -> None:
|
|
"""Fragments with project_name not in plan project_links get view=None."""
|
|
frag_alpha = _make_tiered_fragment(
|
|
fragment_id="frag-alpha",
|
|
project_name="proj-alpha",
|
|
resource_id="res:alpha",
|
|
content="alpha content",
|
|
metadata={"path": "src/alpha.py"},
|
|
)
|
|
frag_orphan = _make_tiered_fragment(
|
|
fragment_id="frag-orphan",
|
|
project_name="proj-unknown",
|
|
resource_id="res:orphan",
|
|
content="orphan content",
|
|
metadata={"path": "src/orphan.py"},
|
|
)
|
|
context.epcov_assembler = _make_assembler(
|
|
scoped_fragments=[frag_alpha, frag_orphan],
|
|
pipeline_result=_make_pipeline_result(),
|
|
)
|
|
|
|
|
|
@given('epcov a plan with project links for "proj-alpha" and "proj-beta"')
|
|
def step_epcov_plan_alpha_beta(context: Context) -> None:
|
|
context.epcov_plan = _make_plan(project_names=["proj-alpha", "proj-beta"])
|
|
|
|
|
|
@given('epcov scoped fragments for "proj-alpha" and "proj-beta"')
|
|
def step_epcov_scoped_fragments_alpha_beta(context: Context) -> None:
|
|
pass # Already set in assembler setup
|
|
|
|
|
|
@then("epcov the assembled result should include only proj-alpha fragments")
|
|
def step_epcov_assembled_only_alpha(context: Context) -> None:
|
|
if context.epcov_error is not None:
|
|
raise AssertionError(f"Unexpected error: {context.epcov_error}")
|
|
result = context.epcov_assembled
|
|
assert result is not None, "Expected non-None assembled result"
|
|
pipeline = context.epcov_assembler._pipeline
|
|
assert pipeline.assemble.called, "Pipeline assemble should have been called"
|
|
call_kwargs = pipeline.assemble.call_args[1]
|
|
frags = call_kwargs.get("fragments", [])
|
|
assert len(frags) == 1, f"Expected 1 fragment, got {len(frags)}"
|
|
assert frags[0].uko_node == "res:alpha"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# assemble: resource filtering (lines 146-153)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@given('epcov an assembler with resource include rule "allowed:*"')
|
|
def step_epcov_assembler_resource_include(context: Context) -> None:
|
|
custom_view = ContextView(include_resources=["allowed:*"])
|
|
policy = ProjectContextPolicy(execute_view=custom_view)
|
|
context.epcov_assembler = _make_assembler(
|
|
policy=policy, pipeline_result=_make_pipeline_result()
|
|
)
|
|
|
|
|
|
@given('epcov scoped fragments with resource ids "allowed:file" and "denied:file"')
|
|
def step_epcov_scoped_frags_resource_filter(context: Context) -> None:
|
|
frag_allowed = _make_tiered_fragment(
|
|
fragment_id="frag-allowed",
|
|
resource_id="allowed:file",
|
|
content="allowed content",
|
|
metadata={"path": "src/allowed.py"},
|
|
)
|
|
frag_denied = _make_tiered_fragment(
|
|
fragment_id="frag-denied",
|
|
resource_id="denied:file",
|
|
content="denied content",
|
|
metadata={"path": "src/denied.py"},
|
|
)
|
|
context.epcov_assembler._tier.get_scoped_view.return_value = [
|
|
frag_allowed,
|
|
frag_denied,
|
|
]
|
|
|
|
|
|
@then("epcov the assembled result should include only the allowed resource fragment")
|
|
def step_epcov_assembled_only_allowed(context: Context) -> None:
|
|
if context.epcov_error is not None:
|
|
raise AssertionError(f"Unexpected error: {context.epcov_error}")
|
|
result = context.epcov_assembled
|
|
assert result is not None, "Expected non-None assembled result"
|
|
pipeline = context.epcov_assembler._pipeline
|
|
assert pipeline.assemble.called, "Pipeline assemble should have been called"
|
|
call_kwargs = pipeline.assemble.call_args[1]
|
|
frags = call_kwargs.get("fragments", [])
|
|
assert len(frags) == 1, f"Expected 1 fragment, got {len(frags)}"
|
|
assert frags[0].uko_node == "allowed:file"
|
|
|
|
|
|
@given('epcov an assembler with resource exclude rule "secret:*"')
|
|
def step_epcov_assembler_resource_exclude(context: Context) -> None:
|
|
custom_view = ContextView(exclude_resources=["secret:*"])
|
|
policy = ProjectContextPolicy(execute_view=custom_view)
|
|
context.epcov_assembler = _make_assembler(
|
|
policy=policy, pipeline_result=_make_pipeline_result()
|
|
)
|
|
|
|
|
|
@given('epcov scoped fragments with resource ids "public:file" and "secret:file"')
|
|
def step_epcov_scoped_frags_resource_exclude(context: Context) -> None:
|
|
frag_public = _make_tiered_fragment(
|
|
fragment_id="frag-public",
|
|
resource_id="public:file",
|
|
content="public content",
|
|
metadata={"path": "src/public.py"},
|
|
)
|
|
frag_secret = _make_tiered_fragment(
|
|
fragment_id="frag-secret",
|
|
resource_id="secret:file",
|
|
content="secret content",
|
|
metadata={"path": "src/secret.py"},
|
|
)
|
|
context.epcov_assembler._tier.get_scoped_view.return_value = [
|
|
frag_public,
|
|
frag_secret,
|
|
]
|
|
|
|
|
|
@then("epcov the assembled result should include only the public resource fragment")
|
|
def step_epcov_assembled_only_public(context: Context) -> None:
|
|
if context.epcov_error is not None:
|
|
raise AssertionError(f"Unexpected error: {context.epcov_error}")
|
|
result = context.epcov_assembled
|
|
assert result is not None, "Expected non-None assembled result"
|
|
pipeline = context.epcov_assembler._pipeline
|
|
assert pipeline.assemble.called, "Pipeline assemble should have been called"
|
|
call_kwargs = pipeline.assemble.call_args[1]
|
|
frags = call_kwargs.get("fragments", [])
|
|
assert len(frags) == 1, f"Expected 1 fragment, got {len(frags)}"
|
|
assert frags[0].uko_node == "public:file"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# assemble: path filtering (lines 155-170)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@given('epcov an assembler with path include rule "src/**"')
|
|
def step_epcov_assembler_path_include(context: Context) -> None:
|
|
custom_view = ContextView(include_paths=["src/**"])
|
|
policy = ProjectContextPolicy(execute_view=custom_view)
|
|
context.epcov_assembler = _make_assembler(
|
|
policy=policy, pipeline_result=_make_pipeline_result()
|
|
)
|
|
|
|
|
|
@given('epcov scoped fragments with paths "src/main.py" and "docs/readme.md"')
|
|
def step_epcov_scoped_frags_path_filter(context: Context) -> None:
|
|
frag_src = _make_tiered_fragment(
|
|
fragment_id="frag-src",
|
|
resource_id="res:src",
|
|
content="source content",
|
|
metadata={"path": "src/main.py"},
|
|
)
|
|
frag_docs = _make_tiered_fragment(
|
|
fragment_id="frag-docs",
|
|
resource_id="res:docs",
|
|
content="docs content",
|
|
metadata={"path": "docs/readme.md"},
|
|
)
|
|
context.epcov_assembler._tier.get_scoped_view.return_value = [
|
|
frag_src,
|
|
frag_docs,
|
|
]
|
|
|
|
|
|
@then("epcov the assembled result should include only the src fragment")
|
|
def step_epcov_assembled_only_src(context: Context) -> None:
|
|
if context.epcov_error is not None:
|
|
raise AssertionError(f"Unexpected error: {context.epcov_error}")
|
|
result = context.epcov_assembled
|
|
assert result is not None, "Expected non-None assembled result"
|
|
pipeline = context.epcov_assembler._pipeline
|
|
assert pipeline.assemble.called, "Pipeline assemble should have been called"
|
|
call_kwargs = pipeline.assemble.call_args[1]
|
|
frags = call_kwargs.get("fragments", [])
|
|
assert len(frags) == 1, f"Expected 1 fragment, got {len(frags)}"
|
|
assert frags[0].provenance.location == "src/main.py"
|
|
|
|
|
|
@given('epcov an assembler with path exclude rule "vendor/**"')
|
|
def step_epcov_assembler_path_exclude(context: Context) -> None:
|
|
custom_view = ContextView(exclude_paths=["vendor/**"])
|
|
policy = ProjectContextPolicy(execute_view=custom_view)
|
|
context.epcov_assembler = _make_assembler(
|
|
policy=policy, pipeline_result=_make_pipeline_result()
|
|
)
|
|
|
|
|
|
@given('epcov scoped fragments with paths "src/main.py" and "vendor/lib.py"')
|
|
def step_epcov_scoped_frags_path_exclude(context: Context) -> None:
|
|
frag_src = _make_tiered_fragment(
|
|
fragment_id="frag-src",
|
|
resource_id="res:src",
|
|
content="source content",
|
|
metadata={"path": "src/main.py"},
|
|
)
|
|
frag_vendor = _make_tiered_fragment(
|
|
fragment_id="frag-vendor",
|
|
resource_id="res:vendor",
|
|
content="vendor content",
|
|
metadata={"path": "vendor/lib.py"},
|
|
)
|
|
context.epcov_assembler._tier.get_scoped_view.return_value = [
|
|
frag_src,
|
|
frag_vendor,
|
|
]
|
|
|
|
|
|
@then("epcov the assembled result should include only the non-vendor fragment")
|
|
def step_epcov_assembled_only_nonvendor(context: Context) -> None:
|
|
if context.epcov_error is not None:
|
|
raise AssertionError(f"Unexpected error: {context.epcov_error}")
|
|
result = context.epcov_assembled
|
|
assert result is not None, "Expected non-None assembled result"
|
|
pipeline = context.epcov_assembler._pipeline
|
|
assert pipeline.assemble.called, "Pipeline assemble should have been called"
|
|
call_kwargs = pipeline.assemble.call_args[1]
|
|
frags = call_kwargs.get("fragments", [])
|
|
assert len(frags) == 1, f"Expected 1 fragment, got {len(frags)}"
|
|
assert frags[0].provenance.location == "src/main.py"
|
|
|
|
|
|
@given("epcov a scoped fragment with no path metadata")
|
|
def step_epcov_scoped_frag_no_path(context: Context) -> None:
|
|
"""Fragment with no path metadata and include_paths set → excluded (line 168-170)."""
|
|
frag = _make_tiered_fragment(
|
|
fragment_id="frag-nopath",
|
|
resource_id="res:nopath",
|
|
content="no path content",
|
|
metadata={},
|
|
)
|
|
context.epcov_assembler._tier.get_scoped_view.return_value = [frag]
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# assemble: max_file_size filtering (lines 172-175)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@given("epcov an assembler with max_file_size of 10 bytes")
|
|
def step_epcov_assembler_max_file_size(context: Context) -> None:
|
|
custom_view = ContextView(max_file_size=10)
|
|
policy = ProjectContextPolicy(execute_view=custom_view)
|
|
context.epcov_assembler = _make_assembler(policy=policy)
|
|
|
|
|
|
@given("epcov a scoped fragment with content exceeding 10 bytes")
|
|
def step_epcov_scoped_frag_big_content(context: Context) -> None:
|
|
frag = _make_tiered_fragment(
|
|
fragment_id="frag-big",
|
|
resource_id="res:big",
|
|
content="this content is definitely more than 10 bytes long",
|
|
metadata={"path": "src/big.py"},
|
|
)
|
|
context.epcov_assembler._tier.get_scoped_view.return_value = [frag]
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# assemble: max_total_size filtering (lines 177-184)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@given("epcov an assembler with max_total_size of 20 bytes")
|
|
def step_epcov_assembler_max_total_size(context: Context) -> None:
|
|
custom_view = ContextView(max_total_size=20)
|
|
policy = ProjectContextPolicy(execute_view=custom_view)
|
|
context.epcov_assembler = _make_assembler(
|
|
policy=policy, pipeline_result=_make_pipeline_result()
|
|
)
|
|
|
|
|
|
@given("epcov two scoped fragments each with 15 byte content")
|
|
def step_epcov_scoped_frags_total_size(context: Context) -> None:
|
|
frag1 = _make_tiered_fragment(
|
|
fragment_id="frag-1",
|
|
resource_id="res:1",
|
|
content="0123456789abcde", # 15 bytes
|
|
metadata={"path": "src/a.py"},
|
|
)
|
|
frag2 = _make_tiered_fragment(
|
|
fragment_id="frag-2",
|
|
resource_id="res:2",
|
|
content="fghijklmnopqrst", # 15 bytes
|
|
metadata={"path": "src/b.py"},
|
|
)
|
|
context.epcov_assembler._tier.get_scoped_view.return_value = [frag1, frag2]
|
|
|
|
|
|
@then("epcov the assembled result should include only the first fragment")
|
|
def step_epcov_assembled_only_first(context: Context) -> None:
|
|
if context.epcov_error is not None:
|
|
raise AssertionError(f"Unexpected error: {context.epcov_error}")
|
|
result = context.epcov_assembled
|
|
assert result is not None, "Expected non-None assembled result"
|
|
pipeline = context.epcov_assembler._pipeline
|
|
assert pipeline.assemble.called, "Pipeline assemble should have been called"
|
|
call_kwargs = pipeline.assemble.call_args[1]
|
|
frags = call_kwargs.get("fragments", [])
|
|
assert len(frags) == 1, f"Expected 1 fragment, got {len(frags)}"
|
|
assert frags[0].uko_node == "res:1"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# assemble: all filtered out (lines 193-203)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@given('epcov an assembler with resource include rule "nonexistent:*"')
|
|
def step_epcov_assembler_resource_nonexistent(context: Context) -> None:
|
|
custom_view = ContextView(include_resources=["nonexistent:*"])
|
|
policy = ProjectContextPolicy(execute_view=custom_view)
|
|
context.epcov_assembler = _make_assembler(policy=policy)
|
|
|
|
|
|
@given('epcov scoped fragments with resource ids "other:a" and "other:b"')
|
|
def step_epcov_scoped_frags_all_excluded(context: Context) -> None:
|
|
frag_a = _make_tiered_fragment(
|
|
fragment_id="frag-a",
|
|
resource_id="other:a",
|
|
content="content a",
|
|
metadata={"path": "src/a.py"},
|
|
)
|
|
frag_b = _make_tiered_fragment(
|
|
fragment_id="frag-b",
|
|
resource_id="other:b",
|
|
content="content b",
|
|
metadata={"path": "src/b.py"},
|
|
)
|
|
context.epcov_assembler._tier.get_scoped_view.return_value = [frag_a, frag_b]
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# assemble: successful full pipeline (lines 186-240)
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@given("epcov an assembler with default policy and pipeline")
|
|
def step_epcov_assembler_full_pipeline(context: Context) -> None:
|
|
from cleveragents.domain.models.acms.crp import (
|
|
ContextFragment as CRPFragment,
|
|
)
|
|
from cleveragents.domain.models.acms.crp import (
|
|
FragmentProvenance as CRPProvenance,
|
|
)
|
|
|
|
mock_frag = CRPFragment(
|
|
uko_node="res:good",
|
|
content="good content here",
|
|
detail_depth=1,
|
|
token_count=10,
|
|
relevance_score=0.5,
|
|
provenance=CRPProvenance(
|
|
resource_uri="res:good",
|
|
location="src/good.py",
|
|
strategy="execute_phase_context",
|
|
),
|
|
)
|
|
pr = _make_pipeline_result()
|
|
pr.fragments = (mock_frag,)
|
|
pr.total_tokens = 10
|
|
pr.budget_used = 0.25
|
|
pr.strategies_used = ("relevance",)
|
|
pr.context_hash = "sha256hash"
|
|
pr.preamble = "Context preamble"
|
|
pr.provenance_map = {"frag-1": {"resource_uri": "res:test"}}
|
|
context.epcov_assembler = _make_assembler(pipeline_result=pr)
|
|
|
|
|
|
@given("epcov scoped fragments that pass all filters")
|
|
def step_epcov_scoped_frags_pass_all(context: Context) -> None:
|
|
frag = _make_tiered_fragment(
|
|
fragment_id="frag-pass",
|
|
resource_id="res:good",
|
|
content="good content here",
|
|
token_count=10,
|
|
metadata={"path": "src/good.py"},
|
|
)
|
|
context.epcov_assembler._tier.get_scoped_view.return_value = [frag]
|
|
|
|
|
|
@then("epcov the assembled result should be an AssembledContext")
|
|
def step_epcov_assembled_is_context(context: Context) -> None:
|
|
if context.epcov_error is not None:
|
|
raise AssertionError(f"Unexpected error: {context.epcov_error}")
|
|
result = context.epcov_assembled
|
|
assert result is not None, "Expected non-None assembled result"
|
|
assert isinstance(result, AssembledContext), (
|
|
f"Expected AssembledContext, got {type(result)}"
|
|
)
|
|
|
|
|
|
@then("epcov the assembled result should have fragments and metadata")
|
|
def step_epcov_assembled_has_data(context: Context) -> None:
|
|
result = context.epcov_assembled
|
|
assert result.total_tokens >= 0, "Expected non-negative total_tokens"
|
|
assert result.budget_used >= 0.0, "Expected non-negative budget_used"
|
|
assert result.context_hash, "Expected non-empty context_hash"
|
|
assert result.strategies_used, "Expected non-empty strategies_used"
|