a41fc02f11
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 14s
CI / build (pull_request) Successful in 17s
CI / quality (pull_request) Successful in 18s
CI / security (pull_request) Successful in 35s
CI / typecheck (pull_request) Successful in 41s
CI / unit_tests (pull_request) Successful in 2m30s
CI / integration_tests (pull_request) Successful in 3m7s
CI / docker (pull_request) Successful in 54s
CI / coverage (pull_request) Successful in 5m42s
CI / lint (push) Successful in 12s
CI / build (push) Successful in 16s
CI / quality (push) Successful in 18s
CI / security (push) Successful in 33s
CI / typecheck (push) Successful in 36s
CI / benchmark-regression (push) Has been skipped
CI / unit_tests (push) Successful in 2m45s
CI / integration_tests (push) Successful in 3m11s
CI / docker (push) Successful in 46s
CI / coverage (push) Successful in 5m52s
CI / benchmark-publish (push) Successful in 17m26s
CI / benchmark-regression (pull_request) Successful in 31m25s
Implement StrategyCoordinator and FusionEngine as named facades over the existing ACMS pipeline components, providing clean public APIs for parallel strategy execution with proportional budget allocation and fragment fusion with dedup/conflict resolution/knapsack packing. Key changes: - Add StrategyCoordinator with parallel execution and confidence-based budget allocation - Add FusionEngine with URI+hash dedup, max-depth conflict resolution, greedy knapsack packing - Add budget overage guard with lowest-relevance fragment dropping - Add per-strategy max caps enforcement - Wire into existing ContextAssemblyPipeline - Add Behave BDD tests, Robot integration tests, ASV benchmarks - Add docs/reference/acms_fusion.md ISSUES CLOSED: #192
610 lines
21 KiB
Python
610 lines
21 KiB
Python
"""Step definitions for features/acms_fusion.feature.
|
|
|
|
Tests the ACMS StrategyCoordinator and FusionEngine facades, covering
|
|
parallel strategy coordination, budget allocation, dedup, depth
|
|
resolution, greedy knapsack packing, and budget overage guard.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Sequence
|
|
from typing import Any
|
|
|
|
from behave import given, then, when
|
|
from behave.runner import Context
|
|
|
|
from cleveragents.application.services.acms_pipeline import (
|
|
CircuitBreaker,
|
|
ParallelStrategyExecutor,
|
|
)
|
|
from cleveragents.application.services.acms_service import StrategyCapabilities
|
|
from cleveragents.application.services.fusion_engine import (
|
|
FusionConfig,
|
|
FusionEngine,
|
|
FusionResult,
|
|
)
|
|
from cleveragents.application.services.strategy_coordinator import (
|
|
CoordinatorConfig,
|
|
StrategyCoordinator,
|
|
)
|
|
from cleveragents.domain.models.core.context_fragment import (
|
|
ContextBudget,
|
|
ContextFragment,
|
|
FragmentProvenance,
|
|
)
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Helpers
|
|
# ---------------------------------------------------------------------------
|
|
|
|
_DEFAULT_PROV = FragmentProvenance(resource_uri="test://fusion")
|
|
|
|
|
|
def _make_frag(**kwargs: Any) -> ContextFragment:
|
|
"""Create a ContextFragment with test defaults."""
|
|
kwargs.setdefault("uko_node", "test://fusion/default")
|
|
kwargs.setdefault("token_count", 10)
|
|
kwargs.setdefault("provenance", _DEFAULT_PROV)
|
|
return ContextFragment(**kwargs)
|
|
|
|
|
|
class _FusionTestStrategy:
|
|
"""Test strategy with configurable confidence."""
|
|
|
|
def __init__(self, name: str = "test_strat", confidence: float = 0.7) -> None:
|
|
self._name = name
|
|
self._confidence = confidence
|
|
|
|
@property
|
|
def name(self) -> str:
|
|
return self._name
|
|
|
|
@property
|
|
def capabilities(self) -> StrategyCapabilities:
|
|
return StrategyCapabilities()
|
|
|
|
def can_handle(self, request: dict[str, Any]) -> float:
|
|
return self._confidence
|
|
|
|
def assemble(
|
|
self,
|
|
fragments: Sequence[ContextFragment],
|
|
budget: ContextBudget,
|
|
) -> Sequence[ContextFragment]:
|
|
result: list[ContextFragment] = []
|
|
total = 0
|
|
for frag in fragments:
|
|
if total + frag.token_count <= budget.available_tokens:
|
|
result.append(frag)
|
|
total += frag.token_count
|
|
return result
|
|
|
|
def explain(self) -> str:
|
|
return f"Test strategy '{self._name}' with confidence {self._confidence}."
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Given steps
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@given("the fusion modules are available")
|
|
def step_fusion_modules_available(context: Context) -> None:
|
|
"""Ensure all fusion modules are importable."""
|
|
pass
|
|
|
|
|
|
@given("fusion test strategies with confidences {c1:g} and {c2:g}")
|
|
def step_fusion_strategies(context: Context, c1: float, c2: float) -> None:
|
|
context.fusion_strategies = [
|
|
_FusionTestStrategy("strat_a", c1),
|
|
_FusionTestStrategy("strat_b", c2),
|
|
]
|
|
|
|
|
|
@given("fusion test fragments with token counts {t1:d} and {t2:d}")
|
|
def step_fusion_fragments(context: Context, t1: int, t2: int) -> None:
|
|
context.fusion_fragments = [
|
|
_make_frag(
|
|
uko_node="project://fusion/a.py",
|
|
content="alpha content",
|
|
token_count=t1,
|
|
relevance_score=0.9,
|
|
),
|
|
_make_frag(
|
|
uko_node="project://fusion/b.py",
|
|
content="beta content",
|
|
token_count=t2,
|
|
relevance_score=0.5,
|
|
),
|
|
]
|
|
|
|
|
|
@given('a coordinator with a pre-broken circuit for "{name}"')
|
|
def step_coordinator_broken_circuit(context: Context, name: str) -> None:
|
|
cb = CircuitBreaker(failure_threshold=1)
|
|
cb.record_failure(name)
|
|
executor = ParallelStrategyExecutor(circuit_breaker=cb)
|
|
context.broken_coordinator = StrategyCoordinator(executor=executor)
|
|
context.broken_strategy_name = name
|
|
|
|
|
|
@given("a coordinator with per-strategy max cap of {cap:d}")
|
|
def step_coordinator_with_cap(context: Context, cap: int) -> None:
|
|
config = CoordinatorConfig(per_strategy_max_cap=cap)
|
|
context.capped_coordinator = StrategyCoordinator(config=config)
|
|
|
|
|
|
@given("fusion fragments with duplicates by URI and content")
|
|
def step_fusion_dup_fragments(context: Context) -> None:
|
|
context.fusion_dup_fragments = [
|
|
_make_frag(
|
|
uko_node="project://fusion/dup.py",
|
|
content="same content here",
|
|
token_count=50,
|
|
relevance_score=0.9,
|
|
),
|
|
_make_frag(
|
|
uko_node="project://fusion/dup.py",
|
|
content="same content here",
|
|
token_count=50,
|
|
relevance_score=0.7,
|
|
),
|
|
_make_frag(
|
|
uko_node="project://fusion/other.py",
|
|
content="different content",
|
|
token_count=50,
|
|
relevance_score=0.5,
|
|
),
|
|
]
|
|
|
|
|
|
@given("fusion fragments with same UKO node at depths {d1:d} and {d2:d}")
|
|
def step_fusion_depth_fragments(context: Context, d1: int, d2: int) -> None:
|
|
context.fusion_depth_fragments = [
|
|
_make_frag(
|
|
uko_node="project://fusion/deep.py",
|
|
content="shallow content",
|
|
token_count=50,
|
|
detail_depth=d1,
|
|
relevance_score=0.8,
|
|
),
|
|
_make_frag(
|
|
uko_node="project://fusion/deep.py",
|
|
content="deep content with more detail",
|
|
token_count=80,
|
|
detail_depth=d2,
|
|
relevance_score=0.7,
|
|
),
|
|
_make_frag(
|
|
uko_node="project://fusion/other.py",
|
|
content="other content",
|
|
token_count=50,
|
|
detail_depth=3,
|
|
relevance_score=0.6,
|
|
),
|
|
]
|
|
|
|
|
|
@given("fusion fragments totaling {total:d} tokens")
|
|
def step_fusion_total_fragments(context: Context, total: int) -> None:
|
|
count = total // 100
|
|
if count < 1:
|
|
count = 1
|
|
per_token = total // count
|
|
context.fusion_total_fragments = [
|
|
_make_frag(
|
|
uko_node=f"project://fusion/file{i}.py",
|
|
content=f"content_{i}",
|
|
token_count=per_token,
|
|
relevance_score=round(0.9 - i * 0.1, 2),
|
|
)
|
|
for i in range(count)
|
|
]
|
|
|
|
|
|
@given("fusion fragments with equal relevance but different depths")
|
|
def step_fusion_tiebreaker_fragments(context: Context) -> None:
|
|
context.fusion_tiebreaker_fragments = [
|
|
_make_frag(
|
|
uko_node="project://fusion/t1.py",
|
|
content="content_t1",
|
|
token_count=50,
|
|
detail_depth=3,
|
|
relevance_score=0.8,
|
|
),
|
|
_make_frag(
|
|
uko_node="project://fusion/t2.py",
|
|
content="content_t2",
|
|
token_count=30,
|
|
detail_depth=7,
|
|
relevance_score=0.8,
|
|
),
|
|
_make_frag(
|
|
uko_node="project://fusion/t3.py",
|
|
content="content_t3",
|
|
token_count=40,
|
|
detail_depth=5,
|
|
relevance_score=0.8,
|
|
),
|
|
]
|
|
|
|
|
|
@given("a fusion engine with overage guard enabled")
|
|
def step_fusion_engine_overage(context: Context) -> None:
|
|
config = FusionConfig(overage_guard_enabled=True, min_fragment_tokens=1)
|
|
context.overage_engine = FusionEngine(config=config)
|
|
|
|
|
|
@given("fusion fragments that cause budget overage")
|
|
def step_fusion_overage_fragments(context: Context) -> None:
|
|
# Create fragments where packer might allow overage.
|
|
# The overage guard is a safety net for when fragments pass through
|
|
# the packer but still exceed budget. We test this by using a custom
|
|
# FusionEngine with a pass-through packer that doesn't enforce budget.
|
|
context.overage_fragments = [
|
|
_make_frag(
|
|
uko_node=f"project://fusion/ov{i}.py",
|
|
content=f"overage_content_{i}",
|
|
token_count=40,
|
|
relevance_score=round(0.9 - i * 0.2, 2),
|
|
)
|
|
for i in range(4)
|
|
]
|
|
|
|
|
|
@given("fusion fragments totaling exactly {total:d} tokens")
|
|
def step_fusion_exact_fragments(context: Context, total: int) -> None:
|
|
context.exact_fragments = [
|
|
_make_frag(
|
|
uko_node="project://fusion/exact.py",
|
|
content="exact content",
|
|
token_count=total,
|
|
relevance_score=0.9,
|
|
),
|
|
]
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# When steps — StrategyCoordinator
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@when("I coordinate with a budget of {budget:d} tokens")
|
|
def step_coordinate(context: Context, budget: int) -> None:
|
|
coordinator = StrategyCoordinator()
|
|
b = ContextBudget(max_tokens=budget, reserved_tokens=0)
|
|
context.coord_result = coordinator.coordinate(
|
|
request={},
|
|
strategies=context.fusion_strategies,
|
|
budget=b,
|
|
fragments=context.fusion_fragments,
|
|
)
|
|
|
|
|
|
@when("I coordinate with no strategies and a budget of {budget:d} tokens")
|
|
def step_coordinate_no_strategies(context: Context, budget: int) -> None:
|
|
coordinator = StrategyCoordinator()
|
|
b = ContextBudget(max_tokens=budget, reserved_tokens=0)
|
|
context.coord_result = coordinator.coordinate(
|
|
request={},
|
|
strategies=[],
|
|
budget=b,
|
|
fragments=context.fusion_fragments,
|
|
)
|
|
|
|
|
|
@when("I coordinate with the circuit-broken strategy")
|
|
def step_coordinate_broken(context: Context) -> None:
|
|
strategy = _FusionTestStrategy(context.broken_strategy_name, 0.7)
|
|
b = ContextBudget(max_tokens=200, reserved_tokens=0)
|
|
context.coord_result = context.broken_coordinator.coordinate(
|
|
request={},
|
|
strategies=[strategy],
|
|
budget=b,
|
|
fragments=context.fusion_fragments,
|
|
)
|
|
|
|
|
|
@when("I coordinate with a budget of {budget:d} tokens using the capped coordinator")
|
|
def step_coordinate_capped(context: Context, budget: int) -> None:
|
|
b = ContextBudget(max_tokens=budget, reserved_tokens=0)
|
|
context.coord_result = context.capped_coordinator.coordinate(
|
|
request={},
|
|
strategies=context.fusion_strategies,
|
|
budget=b,
|
|
fragments=context.fusion_fragments,
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# When steps — FusionEngine
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@when("I fuse with a budget of {budget:d} tokens")
|
|
def step_fuse(context: Context, budget: int) -> None:
|
|
engine = FusionEngine(config=FusionConfig(min_fragment_tokens=1))
|
|
b = ContextBudget(max_tokens=budget, reserved_tokens=0)
|
|
# Use whichever fragments are available
|
|
frags = getattr(
|
|
context,
|
|
"fusion_dup_fragments",
|
|
getattr(
|
|
context,
|
|
"fusion_depth_fragments",
|
|
getattr(
|
|
context,
|
|
"fusion_total_fragments",
|
|
getattr(context, "fusion_tiebreaker_fragments", []),
|
|
),
|
|
),
|
|
)
|
|
context.fusion_result = engine.fuse(frags, b)
|
|
context.fusion_input_count = len(frags)
|
|
|
|
|
|
@when("I fuse with the overage-prone fragments and a budget of {budget:d} tokens")
|
|
def step_fuse_overage(context: Context, budget: int) -> None:
|
|
b = ContextBudget(max_tokens=budget, reserved_tokens=0)
|
|
# Test the overage guard directly since the packer already respects budget.
|
|
# We call _budget_overage_guard on fragments that exceed the budget.
|
|
surviving, dropped = FusionEngine._budget_overage_guard(
|
|
list(context.overage_fragments), b
|
|
)
|
|
total_tokens = sum(f.token_count for f in surviving)
|
|
available = b.available_tokens
|
|
context.fusion_result = FusionResult(
|
|
fragments=surviving,
|
|
input_count=len(context.overage_fragments),
|
|
dedup_count=0,
|
|
depth_resolved_count=0,
|
|
packed_count=len(surviving),
|
|
dropped_by_overage_guard=dropped,
|
|
total_tokens=total_tokens,
|
|
budget_utilization=round(
|
|
min(total_tokens / available if available > 0 else 0.0, 1.0), 4
|
|
),
|
|
)
|
|
|
|
|
|
@when("I fuse with the exact fragments and a budget of {budget:d} tokens")
|
|
def step_fuse_exact(context: Context, budget: int) -> None:
|
|
b = ContextBudget(max_tokens=budget, reserved_tokens=0)
|
|
context.fusion_result = context.overage_engine.fuse(context.exact_fragments, b)
|
|
|
|
|
|
@when("I fuse with no fragments and a budget of {budget:d} tokens")
|
|
def step_fuse_empty(context: Context, budget: int) -> None:
|
|
engine = FusionEngine()
|
|
b = ContextBudget(max_tokens=budget, reserved_tokens=0)
|
|
context.fusion_result = engine.fuse([], b)
|
|
|
|
|
|
@when("I coordinate then fuse with a budget of {budget:d} tokens")
|
|
def step_coordinate_then_fuse(context: Context, budget: int) -> None:
|
|
coordinator = StrategyCoordinator()
|
|
b = ContextBudget(max_tokens=budget, reserved_tokens=0)
|
|
coord_result = coordinator.coordinate(
|
|
request={},
|
|
strategies=context.fusion_strategies,
|
|
budget=b,
|
|
fragments=context.fusion_fragments,
|
|
)
|
|
engine = FusionEngine(config=FusionConfig(min_fragment_tokens=1))
|
|
context.fusion_result = engine.fuse(coord_result.fragments, b)
|
|
context.integration_budget = budget
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# When steps — Config
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@when("I create a default CoordinatorConfig")
|
|
def step_create_coord_config(context: Context) -> None:
|
|
context.coord_config = CoordinatorConfig()
|
|
|
|
|
|
@when("I create a default FusionConfig")
|
|
def step_create_fusion_config(context: Context) -> None:
|
|
context.fusion_config = FusionConfig()
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Then steps — StrategyCoordinator
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@then("the coordination result should contain fragments")
|
|
def step_coord_has_fragments(context: Context) -> None:
|
|
assert len(context.coord_result.fragments) > 0, (
|
|
"Expected fragments from coordination"
|
|
)
|
|
|
|
|
|
@then("the coordination result should list strategies used")
|
|
def step_coord_strategies_used(context: Context) -> None:
|
|
assert len(context.coord_result.strategies_used) > 0, (
|
|
"Expected strategies used in result"
|
|
)
|
|
|
|
|
|
@then("the coordination result should contain {count:d} fragments")
|
|
def step_coord_count(context: Context, count: int) -> None:
|
|
assert len(context.coord_result.fragments) == count, (
|
|
f"Expected {count} fragments, got {len(context.coord_result.fragments)}"
|
|
)
|
|
|
|
|
|
@then("the coordination result should report circuit-broken strategies")
|
|
def step_coord_circuit_broken(context: Context) -> None:
|
|
assert len(context.coord_result.circuit_broken) > 0, (
|
|
"Expected circuit-broken strategies in result"
|
|
)
|
|
|
|
|
|
@then("the allocation for the first strategy should be approximately {tokens:d}")
|
|
def step_coord_alloc_first(context: Context, tokens: int) -> None:
|
|
first_alloc = context.coord_result.allocations[0][2]
|
|
assert abs(first_alloc - tokens) <= 1, (
|
|
f"First allocation {first_alloc}, expected ~{tokens}"
|
|
)
|
|
|
|
|
|
@then("the allocation for the second strategy should be approximately {tokens:d}")
|
|
def step_coord_alloc_second(context: Context, tokens: int) -> None:
|
|
second_alloc = context.coord_result.allocations[1][2]
|
|
assert abs(second_alloc - tokens) <= 1, (
|
|
f"Second allocation {second_alloc}, expected ~{tokens}"
|
|
)
|
|
|
|
|
|
@then("the total allocation should equal {total:d}")
|
|
def step_coord_alloc_total(context: Context, total: int) -> None:
|
|
actual = sum(a[2] for a in context.coord_result.allocations)
|
|
assert actual == total, f"Total allocation {actual} != {total}"
|
|
|
|
|
|
@then("no strategy allocation should exceed {cap:d} tokens")
|
|
def step_coord_cap_enforced(context: Context, cap: int) -> None:
|
|
for name, _, tokens in context.coord_result.allocations:
|
|
assert tokens <= cap, f"Strategy {name} allocated {tokens} > cap {cap}"
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Then steps — FusionEngine
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@then("the fusion result dedup count should be greater than 0")
|
|
def step_fusion_dedup_count(context: Context) -> None:
|
|
assert context.fusion_result.dedup_count > 0, (
|
|
f"Expected dedup_count > 0, got {context.fusion_result.dedup_count}"
|
|
)
|
|
|
|
|
|
@then("the fusion result should contain fewer fragments than input")
|
|
def step_fusion_fewer(context: Context) -> None:
|
|
assert len(context.fusion_result.fragments) < context.fusion_input_count, (
|
|
f"Expected fewer fragments ({len(context.fusion_result.fragments)}) "
|
|
f"than input ({context.fusion_input_count})"
|
|
)
|
|
|
|
|
|
@then("the fusion result should retain the depth {depth:d} fragment")
|
|
def step_fusion_depth_retained(context: Context, depth: int) -> None:
|
|
depths = [f.detail_depth for f in context.fusion_result.fragments]
|
|
# After scoring, the depth values should still be present
|
|
# The max-depth fragment should survive for the node
|
|
node_frags = [f for f in context.fusion_result.fragments if "deep" in f.uko_node]
|
|
if node_frags:
|
|
max_depth = max(f.detail_depth for f in node_frags)
|
|
assert max_depth == depth, (
|
|
f"Expected depth {depth} retained, got max {max_depth} in {depths}"
|
|
)
|
|
|
|
|
|
@then("the fusion result depth resolved count should be greater than 0")
|
|
def step_fusion_depth_resolved(context: Context) -> None:
|
|
assert context.fusion_result.depth_resolved_count > 0, (
|
|
f"Expected depth_resolved > 0, got {context.fusion_result.depth_resolved_count}"
|
|
)
|
|
|
|
|
|
@then("the fusion result total tokens should be at most {max_tokens:d}")
|
|
def step_fusion_within_budget(context: Context, max_tokens: int) -> None:
|
|
assert context.fusion_result.total_tokens <= max_tokens, (
|
|
f"Total tokens {context.fusion_result.total_tokens} > {max_tokens}"
|
|
)
|
|
|
|
|
|
@then(
|
|
"the fusion result fragments should be ordered by depth descending "
|
|
"then token count ascending"
|
|
)
|
|
def step_fusion_tiebreakers(context: Context) -> None:
|
|
frags = context.fusion_result.fragments
|
|
if len(frags) <= 1:
|
|
return
|
|
# Verify tie-breaker ordering within same relevance group
|
|
for i in range(len(frags) - 1):
|
|
a, b = frags[i], frags[i + 1]
|
|
if (
|
|
abs(a.relevance_score - b.relevance_score) < 0.001
|
|
and a.detail_depth == b.detail_depth
|
|
):
|
|
# Same relevance and depth: token count ascending
|
|
assert a.token_count <= b.token_count, (
|
|
f"Token count tie-breaker failed: {a.token_count} > {b.token_count}"
|
|
)
|
|
|
|
|
|
@then("the fusion result dropped by overage guard should be greater than 0")
|
|
def step_fusion_overage_dropped(context: Context) -> None:
|
|
assert context.fusion_result.dropped_by_overage_guard > 0, (
|
|
f"Expected drops > 0, got {context.fusion_result.dropped_by_overage_guard}"
|
|
)
|
|
|
|
|
|
@then("the fusion result dropped by overage guard should be {count:d}")
|
|
def step_fusion_overage_exact(context: Context, count: int) -> None:
|
|
assert context.fusion_result.dropped_by_overage_guard == count, (
|
|
f"Expected {count} drops, got {context.fusion_result.dropped_by_overage_guard}"
|
|
)
|
|
|
|
|
|
@then("the fusion result should contain {count:d} fragments")
|
|
def step_fusion_count(context: Context, count: int) -> None:
|
|
assert len(context.fusion_result.fragments) == count, (
|
|
f"Expected {count} fragments, got {len(context.fusion_result.fragments)}"
|
|
)
|
|
|
|
|
|
@then("the fusion result input count should be {count:d}")
|
|
def step_fusion_input(context: Context, count: int) -> None:
|
|
assert context.fusion_result.input_count == count, (
|
|
f"Expected input_count {count}, got {context.fusion_result.input_count}"
|
|
)
|
|
|
|
|
|
@then("the final fused result should contain fragments within budget")
|
|
def step_integration_result(context: Context) -> None:
|
|
assert len(context.fusion_result.fragments) > 0, (
|
|
"Expected fragments from integration"
|
|
)
|
|
assert context.fusion_result.total_tokens <= context.integration_budget, (
|
|
f"Total tokens {context.fusion_result.total_tokens} "
|
|
f"> budget {context.integration_budget}"
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Then steps — Config
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
@then("the config min_useful_budget should be {val:d}")
|
|
def step_config_min_budget(context: Context, val: int) -> None:
|
|
assert context.coord_config.min_useful_budget == val
|
|
|
|
|
|
@then("the config executor_timeout should be {val:g}")
|
|
def step_config_timeout(context: Context, val: float) -> None:
|
|
assert context.coord_config.executor_timeout == val
|
|
|
|
|
|
@then("the config per_strategy_max_cap should be None")
|
|
def step_config_cap_none(context: Context) -> None:
|
|
assert context.coord_config.per_strategy_max_cap is None
|
|
|
|
|
|
@then("the fusion config overage_guard_enabled should be True")
|
|
def step_fusion_config_overage(context: Context) -> None:
|
|
assert context.fusion_config.overage_guard_enabled is True
|
|
|
|
|
|
@then("the fusion config min_fragment_tokens should be {val:d}")
|
|
def step_fusion_config_min_tokens(context: Context, val: int) -> None:
|
|
assert context.fusion_config.min_fragment_tokens == val
|