Compare commits
3 Commits
pr-practice
...
pr-9329
| Author | SHA1 | Date | |
|---|---|---|---|
| 19d2d931e7 | |||
| ca631fd8b0 | |||
| a0759abb49 |
@@ -284,6 +284,8 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
||||
message listing available built-in profiles. The resolved profile name is also
|
||||
logged at debug level for observability.
|
||||
|
||||
- **ACMS StrategyCapabilities Consolidation** (#9161): Removed duplicate `StrategyCapabilities` dataclass from `acms_service.py` and unified to the canonical Pydantic v2 domain model from `domain/models/acms/strategy`. Fixed legacy parameter names (`supports_semantic_search`, `supports_graph_navigation`, `supports_temporal_archaeology`) across all strategy implementations in `context_strategies.py` and `acms_advanced_strategies.py`. Added non-empty `resource_types` declarations on all pipeline strategies, resolving `validate_registry()` warnings.
|
||||
|
||||
### Added
|
||||
|
||||
- **ACMS Large-Project Indexing BDD Coverage** (#8726): Added 7 Behave scenarios
|
||||
|
||||
@@ -30,3 +30,4 @@ Below are some of the specific details of various contributions.
|
||||
* HAL 9000 has contributed the git_tools TOCTOU race condition fix (PR #8255 / issue #7619): eliminated the Time-Of-Check-To-Time-Of-Use race in `_get_base_env()` by adding double-checked locking with a module-level `threading.Lock`, preventing concurrent threads from writing conflicting environment snapshots.
|
||||
* HAL 9000 has contributed comprehensive milestone documentation for v3.6.0 (Advanced Concepts & Deferred Features) and v3.7.0 (TUI Implementation) (PR #9903): split into sub-documents covering context strategies, LLM backends, resource types, A2A rename, container tool execution, scope chain resolution, cost/safety budgets, E2E workflow tests, code review examples, plugin architecture, TUI layout, persona system, reference/command input, session management, configuration, and TuiMaterializer integration.
|
||||
* HAL 9000 has contributed the LLMTraceRepository data-integrity fix (PR #8185 / issue #7505): replaced the unconditional `session.commit()` in `LLMTraceRepository.save()` with a dual-path implementation that respects the UnitOfWork pattern — flushing only when an external session is provided, and flushing + committing + closing when operating standalone. This eliminates premature transaction commits, loss of rollback capability, and a docstring/implementation mismatch.
|
||||
* HAL 9000 has contributed the ACMS StrategyCapabilities consolidation (PR #9329 / issue #9161): removed the duplicate `StrategyCapabilities` dataclass from `acms_service.py` and unified to the canonical Pydantic v2 domain model from `domain/models/acms/strategy`. Fixed legacy parameter names (`supports_semantic_search`, `supports_graph_navigation`, `supports_temporal_archaeology`) across all 6 built-in strategies. Added non-empty `resource_types` declarations on all pipeline strategies, resolving `validate_registry()` warnings. Added BDD regression test coverage (17 scenarios).
|
||||
|
||||
@@ -52,9 +52,9 @@ Feature: ACMS advanced strategies coverage boost
|
||||
|
||||
Scenario: TemporalArchaeologyStrategy capabilities include temporal and graph support
|
||||
Given a TemporalArchaeologyStrategy instance
|
||||
Then its capabilities have supports_temporal_archaeology true
|
||||
And its capabilities have supports_graph_navigation true
|
||||
And its capabilities have supports_semantic_search false
|
||||
Then its capabilities have uses_temporal true
|
||||
And its capabilities have uses_graph true
|
||||
And its capabilities have uses_vector false
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# PlanDecisionContextStrategy.capabilities (lines 364-365)
|
||||
@@ -62,6 +62,6 @@ Feature: ACMS advanced strategies coverage boost
|
||||
|
||||
Scenario: PlanDecisionContextStrategy capabilities include temporal support only
|
||||
Given a PlanDecisionContextStrategy instance
|
||||
Then its capabilities have supports_temporal_archaeology true
|
||||
And its capabilities have supports_graph_navigation false
|
||||
And its capabilities have supports_semantic_search false
|
||||
Then its capabilities have uses_temporal true
|
||||
And its capabilities have uses_graph false
|
||||
And its capabilities have uses_vector false
|
||||
|
||||
@@ -514,11 +514,11 @@ Feature: ACMS v1 Context Assembly Pipeline
|
||||
Scenario: Each built-in strategy declares distinct capabilities
|
||||
Given the ACMS pipeline modules are available
|
||||
When I inspect the capabilities of "relevance"
|
||||
Then the strategy should declare supports_semantic_search as true
|
||||
Then the strategy should declare uses_vector as true
|
||||
When I inspect the capabilities of "recency"
|
||||
Then the strategy should declare supports_temporal_archaeology as true
|
||||
Then the strategy should declare uses_temporal as true
|
||||
When I inspect the capabilities of "tiered"
|
||||
Then the strategy should declare supports_semantic_search as false
|
||||
Then the strategy should declare uses_vector as false
|
||||
|
||||
@acms_strategy @introspection
|
||||
Scenario: Strategy confidence ranking determines selector priority
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
@acms @strategy @regression
|
||||
Feature: ACMS StrategyCapabilities consolidation regression tests
|
||||
As a developer maintaining the ACMS pipeline
|
||||
I want to verify that all 6 built-in strategies use the consolidated
|
||||
domain-model StrategyCapabilities with spec-compliant fields
|
||||
So that validate_registry() produces no warnings for any built-in strategy
|
||||
|
||||
# Regression tests for issue #9161:
|
||||
# Consolidate StrategyCapabilities to single domain model with spec-compliant fields.
|
||||
# All 6 built-in strategies must declare:
|
||||
# - At least one backend capability (uses_text, uses_vector, uses_graph, uses_temporal)
|
||||
# - Non-empty resource_types (AC#7 from issue #9161)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# validate_registry() — all 6 built-in strategies produce no warnings
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@strategy_validation
|
||||
Scenario: validate_registry produces no warnings when all 6 built-in strategies are registered
|
||||
Given a registry with all built-in strategies
|
||||
When I validate the registry
|
||||
Then there should be no validation warnings
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Individual strategy: resource_types must be non-empty (AC#7)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@strategy_validation
|
||||
Scenario: simple-keyword strategy declares non-empty resource_types
|
||||
Given all built-in strategies are instantiated
|
||||
Then the strategy "simple-keyword" should declare non-empty resource_types
|
||||
|
||||
@strategy_validation
|
||||
Scenario: semantic-embedding strategy declares non-empty resource_types
|
||||
Given all built-in strategies are instantiated
|
||||
Then the strategy "semantic-embedding" should declare non-empty resource_types
|
||||
|
||||
@strategy_validation
|
||||
Scenario: breadth-depth-navigator strategy declares non-empty resource_types
|
||||
Given all built-in strategies are instantiated
|
||||
Then the strategy "breadth-depth-navigator" should declare non-empty resource_types
|
||||
|
||||
@strategy_validation
|
||||
Scenario: arce strategy declares non-empty resource_types
|
||||
Given all built-in strategies are instantiated
|
||||
Then the strategy "arce" should declare non-empty resource_types
|
||||
|
||||
@strategy_validation
|
||||
Scenario: temporal-archaeology strategy declares non-empty resource_types
|
||||
Given all built-in strategies are instantiated
|
||||
Then the strategy "temporal-archaeology" should declare non-empty resource_types
|
||||
|
||||
@strategy_validation
|
||||
Scenario: plan-decision-context strategy declares non-empty resource_types
|
||||
Given all built-in strategies are instantiated
|
||||
Then the strategy "plan-decision-context" should declare non-empty resource_types
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Individual strategy: at least one backend capability declared
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@strategy_validation
|
||||
Scenario: simple-keyword strategy declares at least one backend capability
|
||||
Given all built-in strategies are instantiated
|
||||
Then the strategy "simple-keyword" should declare at least one backend capability
|
||||
|
||||
@strategy_validation
|
||||
Scenario: semantic-embedding strategy declares at least one backend capability
|
||||
Given all built-in strategies are instantiated
|
||||
Then the strategy "semantic-embedding" should declare at least one backend capability
|
||||
|
||||
@strategy_validation
|
||||
Scenario: breadth-depth-navigator strategy declares at least one backend capability
|
||||
Given all built-in strategies are instantiated
|
||||
Then the strategy "breadth-depth-navigator" should declare at least one backend capability
|
||||
|
||||
@strategy_validation
|
||||
Scenario: arce strategy declares at least one backend capability
|
||||
Given all built-in strategies are instantiated
|
||||
Then the strategy "arce" should declare at least one backend capability
|
||||
|
||||
@strategy_validation
|
||||
Scenario: temporal-archaeology strategy declares at least one backend capability
|
||||
Given all built-in strategies are instantiated
|
||||
Then the strategy "temporal-archaeology" should declare at least one backend capability
|
||||
|
||||
@strategy_validation
|
||||
Scenario: plan-decision-context strategy declares at least one backend capability
|
||||
Given all built-in strategies are instantiated
|
||||
Then the strategy "plan-decision-context" should declare at least one backend capability
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# StrategyCapabilities uses spec-compliant field names (not legacy names)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@strategy_validation
|
||||
Scenario: StrategyCapabilities uses spec-compliant field names
|
||||
Given all built-in strategies are instantiated
|
||||
Then every strategy capabilities should use spec-compliant field names
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Pipeline strategies (RelevanceStrategy, RecencyStrategy, TieredStrategy)
|
||||
# also declare non-empty resource_types (AC#7)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@strategy_validation
|
||||
Scenario: RelevanceStrategy declares non-empty resource_types
|
||||
Given the ACMS pipeline built-in strategies are instantiated
|
||||
Then the pipeline strategy "relevance" should declare non-empty resource_types
|
||||
|
||||
@strategy_validation
|
||||
Scenario: RecencyStrategy declares non-empty resource_types
|
||||
Given the ACMS pipeline built-in strategies are instantiated
|
||||
Then the pipeline strategy "recency" should declare non-empty resource_types
|
||||
|
||||
@strategy_validation
|
||||
Scenario: TieredStrategy declares non-empty resource_types
|
||||
Given the ACMS pipeline built-in strategies are instantiated
|
||||
Then the pipeline strategy "tiered" should declare non-empty resource_types
|
||||
@@ -275,19 +275,19 @@ def step_temporal_instance(context: Context) -> None:
|
||||
context.strategy = TemporalArchaeologyStrategy()
|
||||
|
||||
|
||||
@then("its capabilities have supports_temporal_archaeology true")
|
||||
@then("its capabilities have uses_temporal true")
|
||||
def step_cap_temporal(context: Context) -> None:
|
||||
assert context.strategy.capabilities.supports_temporal_archaeology is True
|
||||
assert context.strategy.capabilities.uses_temporal is True
|
||||
|
||||
|
||||
@then("its capabilities have supports_graph_navigation true")
|
||||
@then("its capabilities have uses_graph true")
|
||||
def step_cap_graph_true(context: Context) -> None:
|
||||
assert context.strategy.capabilities.supports_graph_navigation is True
|
||||
assert context.strategy.capabilities.uses_graph is True
|
||||
|
||||
|
||||
@then("its capabilities have supports_semantic_search false")
|
||||
def step_cap_semantic_false(context: Context) -> None:
|
||||
assert context.strategy.capabilities.supports_semantic_search is False
|
||||
@then("its capabilities have uses_vector false")
|
||||
def step_cap_vector_false(context: Context) -> None:
|
||||
assert context.strategy.capabilities.uses_vector is False
|
||||
|
||||
|
||||
# ===================================================================
|
||||
@@ -300,6 +300,6 @@ def step_plan_decision_instance(context: Context) -> None:
|
||||
context.strategy = PlanDecisionContextStrategy()
|
||||
|
||||
|
||||
@then("its capabilities have supports_graph_navigation false")
|
||||
@then("its capabilities have uses_graph false")
|
||||
def step_cap_graph_false(context: Context) -> None:
|
||||
assert context.strategy.capabilities.supports_graph_navigation is False
|
||||
assert context.strategy.capabilities.uses_graph is False
|
||||
|
||||
@@ -364,7 +364,7 @@ def step_arce_name(context: Context, expected: str) -> None:
|
||||
|
||||
@then("the ArceStrategy should support semantic search")
|
||||
def step_arce_supports_semantic(context: Context) -> None:
|
||||
assert context.arce_strategy.capabilities.supports_semantic_search
|
||||
assert context.arce_strategy.capabilities.uses_vector
|
||||
|
||||
|
||||
@then('the ArceStrategy explain should contain "{text}"')
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
"""Step definitions for acms_strategy_capabilities_regression.feature.
|
||||
|
||||
Regression tests for issue #9161: Consolidate StrategyCapabilities to single
|
||||
domain model with spec-compliant fields.
|
||||
|
||||
Verifies that:
|
||||
- All 6 built-in strategies (from strategy_stubs.py) declare non-empty
|
||||
resource_types (AC#7) and at least one backend capability.
|
||||
- validate_registry() produces no warnings for any built-in strategy.
|
||||
- StrategyCapabilities uses spec-compliant field names (uses_text, uses_vector,
|
||||
uses_graph, uses_temporal) rather than legacy names.
|
||||
- Pipeline strategies (RelevanceStrategy, RecencyStrategy, TieredStrategy)
|
||||
also declare non-empty resource_types.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from behave import given, then
|
||||
from behave.runner import Context
|
||||
|
||||
from cleveragents.application.services.acms_service import (
|
||||
RelevanceStrategy,
|
||||
RecencyStrategy,
|
||||
TieredStrategy,
|
||||
)
|
||||
from cleveragents.application.services.strategy_registry import (
|
||||
StrategyRegistry,
|
||||
)
|
||||
from cleveragents.domain.models.acms.strategy import (
|
||||
StrategyCapabilities,
|
||||
StrategyConfig,
|
||||
)
|
||||
from cleveragents.domain.models.acms.strategy_stubs import (
|
||||
BUILTIN_STRATEGY_CLASSES,
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _all_builtins() -> dict[str, object]:
|
||||
"""Instantiate all 6 built-in strategies keyed by name."""
|
||||
instances: dict[str, object] = {}
|
||||
for cls in BUILTIN_STRATEGY_CLASSES:
|
||||
inst = cls()
|
||||
instances[inst.name] = inst
|
||||
return instances
|
||||
|
||||
|
||||
def _register_all_builtins(registry: StrategyRegistry) -> None:
|
||||
"""Register all 6 built-in strategies in the registry."""
|
||||
for cls in BUILTIN_STRATEGY_CLASSES:
|
||||
inst = cls()
|
||||
registry.register(
|
||||
inst,
|
||||
config=StrategyConfig(enabled=True),
|
||||
is_builtin=True,
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Given
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@given("a registry with all built-in strategies")
|
||||
def step_given_registry_with_builtins(context: Context) -> None:
|
||||
"""Set up a fresh StrategyRegistry populated with all 6 built-in strategies."""
|
||||
context.registry = StrategyRegistry()
|
||||
_register_all_builtins(context.registry)
|
||||
|
||||
|
||||
@given("all built-in strategies are instantiated")
|
||||
def step_given_all_builtins_instantiated(context: Context) -> None:
|
||||
"""Instantiate all 6 built-in strategies and store them in context."""
|
||||
context.strategies = _all_builtins()
|
||||
|
||||
|
||||
@given("the ACMS pipeline built-in strategies are instantiated")
|
||||
def step_given_pipeline_builtins(context: Context) -> None:
|
||||
"""Instantiate the 3 pipeline built-in strategies."""
|
||||
context.pipeline_strategies = {
|
||||
"relevance": RelevanceStrategy(),
|
||||
"recency": RecencyStrategy(),
|
||||
"tiered": TieredStrategy(),
|
||||
}
|
||||
|
||||
|
||||
@when("I validate the registry")
|
||||
def step_when_validate_registry(context: Context) -> None:
|
||||
"""Validate the registry and capture any warnings produced."""
|
||||
context.validation_messages = context.registry.validate()
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Then
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@then("there should be no validation warnings")
|
||||
def step_then_no_validation_warnings(context: Context) -> None:
|
||||
"""Verify that validate_registry() produced no warning messages."""
|
||||
assert context.validation_messages is not None, (
|
||||
"No validation was run — did you forget @when('I validate the registry')?"
|
||||
)
|
||||
warnings = [m for m in context.validation_messages if "warning" in m.lower()]
|
||||
assert not warnings, (
|
||||
f"validate_registry() produced {len(warnings)} warning(s): "
|
||||
+ "; ".join(warnings)
|
||||
)
|
||||
|
||||
|
||||
@then('the strategy "{name}" should declare non-empty resource_types')
|
||||
def step_then_nonempty_resource_types(context: Context, name: str) -> None:
|
||||
"""Verify that the named strategy declares non-empty resource_types."""
|
||||
strategy = context.strategies[name]
|
||||
caps = strategy.capabilities
|
||||
assert isinstance(caps, StrategyCapabilities), (
|
||||
f"Strategy '{name}' capabilities is not StrategyCapabilities, "
|
||||
f"got {type(caps).__name__}"
|
||||
)
|
||||
assert caps.resource_types, (
|
||||
f"Strategy '{name}' has empty resource_types — violates AC#7 of issue #9161. "
|
||||
f"All built-in strategies must declare at least one supported resource type."
|
||||
)
|
||||
|
||||
|
||||
@then('the strategy "{name}" should declare at least one backend capability')
|
||||
def step_then_has_backend_capability(context: Context, name: str) -> None:
|
||||
"""Verify that the named strategy declares at least one backend capability."""
|
||||
strategy = context.strategies[name]
|
||||
caps = strategy.capabilities
|
||||
assert isinstance(caps, StrategyCapabilities), (
|
||||
f"Strategy '{name}' capabilities is not StrategyCapabilities"
|
||||
)
|
||||
has_any = (
|
||||
caps.uses_text or caps.uses_vector or caps.uses_graph or caps.uses_temporal
|
||||
)
|
||||
assert has_any, (
|
||||
f"Strategy '{name}' declares no backend capabilities "
|
||||
f"(uses_text={caps.uses_text}, uses_vector={caps.uses_vector}, "
|
||||
f"uses_graph={caps.uses_graph}, uses_temporal={caps.uses_temporal}). "
|
||||
f"Every strategy must declare at least one backend capability."
|
||||
)
|
||||
|
||||
|
||||
@then("every strategy capabilities should use spec-compliant field names")
|
||||
def step_then_spec_compliant_fields(context: Context) -> None:
|
||||
"""Verify that StrategyCapabilities uses spec-compliant field names.
|
||||
|
||||
The consolidated domain model uses:
|
||||
- uses_text (not supports_semantic_search)
|
||||
- uses_vector (not supports_semantic_search)
|
||||
- uses_graph (not supports_graph_navigation)
|
||||
- uses_temporal (not supports_temporal_archaeology)
|
||||
|
||||
This test verifies that the legacy field names are NOT present on the
|
||||
StrategyCapabilities model, confirming the consolidation is complete.
|
||||
"""
|
||||
for name, strategy in context.strategies.items():
|
||||
caps = strategy.capabilities
|
||||
assert isinstance(caps, StrategyCapabilities), (
|
||||
f"Strategy '{name}' capabilities is not StrategyCapabilities"
|
||||
)
|
||||
# Verify spec-compliant fields exist
|
||||
assert hasattr(caps, "uses_text"), (
|
||||
f"Strategy '{name}' StrategyCapabilities missing 'uses_text' field"
|
||||
)
|
||||
assert hasattr(caps, "uses_vector"), (
|
||||
f"Strategy '{name}' StrategyCapabilities missing 'uses_vector' field"
|
||||
)
|
||||
assert hasattr(caps, "uses_graph"), (
|
||||
f"Strategy '{name}' StrategyCapabilities missing 'uses_graph' field"
|
||||
)
|
||||
assert hasattr(caps, "uses_temporal"), (
|
||||
f"Strategy '{name}' StrategyCapabilities missing 'uses_temporal' field"
|
||||
)
|
||||
# Verify legacy field names are NOT present
|
||||
assert not hasattr(caps, "supports_semantic_search"), (
|
||||
f"Strategy '{name}' StrategyCapabilities still has legacy "
|
||||
f"'supports_semantic_search' field — consolidation incomplete"
|
||||
)
|
||||
assert not hasattr(caps, "supports_graph_navigation"), (
|
||||
f"Strategy '{name}' StrategyCapabilities still has legacy "
|
||||
f"'supports_graph_navigation' field — consolidation incomplete"
|
||||
)
|
||||
assert not hasattr(caps, "supports_temporal_archaeology"), (
|
||||
f"Strategy '{name}' StrategyCapabilities still has legacy "
|
||||
f"'supports_temporal_archaeology' field — consolidation incomplete"
|
||||
)
|
||||
|
||||
|
||||
@then('the pipeline strategy "{name}" should declare non-empty resource_types')
|
||||
def step_then_pipeline_nonempty_resource_types(context: Context, name: str) -> None:
|
||||
"""Verify that the named pipeline strategy declares non-empty resource_types."""
|
||||
strategy = context.pipeline_strategies[name]
|
||||
caps = strategy.capabilities
|
||||
assert isinstance(caps, StrategyCapabilities), (
|
||||
f"Pipeline strategy '{name}' capabilities is not StrategyCapabilities, "
|
||||
f"got {type(caps).__name__}"
|
||||
)
|
||||
assert caps.resource_types, (
|
||||
f"Pipeline strategy '{name}' has empty resource_types — violates AC#7 of "
|
||||
f"issue #9161. All pipeline strategies must declare at least one supported "
|
||||
f"resource type."
|
||||
)
|
||||
@@ -239,8 +239,8 @@ def step_strategy_confidence(context: Context, expected: float) -> None:
|
||||
@then("the SimpleKeywordStrategy should not support semantic search")
|
||||
def step_simple_keyword_no_semantic(context: Context) -> None:
|
||||
caps = context.strategy.capabilities
|
||||
assert not caps.supports_semantic_search, (
|
||||
"SimpleKeywordStrategy should NOT support semantic search"
|
||||
assert not caps.uses_vector, (
|
||||
"SimpleKeywordStrategy should NOT support vector/semantic search"
|
||||
)
|
||||
|
||||
|
||||
@@ -253,8 +253,8 @@ def step_simple_keyword_name(context: Context, name: str) -> None:
|
||||
@then("the SemanticEmbeddingStrategy should support semantic search")
|
||||
def step_semantic_supports_search(context: Context) -> None:
|
||||
caps = context.strategy.capabilities
|
||||
assert caps.supports_semantic_search, (
|
||||
"SemanticEmbeddingStrategy should support semantic search"
|
||||
assert caps.uses_vector, (
|
||||
"SemanticEmbeddingStrategy should support vector/semantic search"
|
||||
)
|
||||
|
||||
|
||||
@@ -267,7 +267,7 @@ def step_semantic_name(context: Context, name: str) -> None:
|
||||
@then("the BreadthDepthNavigatorStrategy should support graph navigation")
|
||||
def step_breadth_depth_supports_graph(context: Context) -> None:
|
||||
caps = context.strategy.capabilities
|
||||
assert caps.supports_graph_navigation, (
|
||||
assert caps.uses_graph, (
|
||||
"BreadthDepthNavigatorStrategy should support graph navigation"
|
||||
)
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ def _test_arce_strategy() -> None:
|
||||
strategy = ArceStrategy(max_iterations=3)
|
||||
assert strategy.name == "arce"
|
||||
assert strategy.can_handle({}) == 0.95
|
||||
assert strategy.capabilities.supports_semantic_search
|
||||
assert strategy.capabilities.uses_vector
|
||||
|
||||
frags = [
|
||||
_frag("project://app/io.py", "async IO handler", 0.7, 20, 5),
|
||||
|
||||
@@ -229,13 +229,13 @@ def _cmd_capabilities() -> int:
|
||||
se = SemanticEmbeddingStrategy()
|
||||
bd = BreadthDepthNavigatorStrategy()
|
||||
|
||||
if sk.capabilities.supports_semantic_search:
|
||||
print("FAIL: SimpleKeyword should not support semantic search")
|
||||
if sk.capabilities.uses_vector:
|
||||
print("FAIL: SimpleKeyword should not support vector/semantic search")
|
||||
return 1
|
||||
if not se.capabilities.supports_semantic_search:
|
||||
print("FAIL: SemanticEmbedding should support semantic search")
|
||||
if not se.capabilities.uses_vector:
|
||||
print("FAIL: SemanticEmbedding should support vector/semantic search")
|
||||
return 1
|
||||
if not bd.capabilities.supports_graph_navigation:
|
||||
if not bd.capabilities.uses_graph:
|
||||
print("FAIL: BreadthDepth should support graph navigation")
|
||||
return 1
|
||||
if sk.name != "simple-keyword":
|
||||
|
||||
@@ -31,9 +31,11 @@ from collections.abc import Sequence
|
||||
from typing import Any, Final
|
||||
|
||||
from cleveragents.application.services.acms_service import (
|
||||
StrategyCapabilities,
|
||||
_pack_budget,
|
||||
)
|
||||
from cleveragents.domain.models.acms.strategy import (
|
||||
StrategyCapabilities,
|
||||
)
|
||||
from cleveragents.domain.models.core.context_fragment import (
|
||||
ContextBudget,
|
||||
ContextFragment,
|
||||
@@ -103,9 +105,10 @@ class ArceStrategy:
|
||||
@property
|
||||
def capabilities(self) -> StrategyCapabilities:
|
||||
return StrategyCapabilities(
|
||||
supports_semantic_search=True,
|
||||
supports_graph_navigation=True,
|
||||
supports_temporal_archaeology=True,
|
||||
uses_vector=True,
|
||||
uses_graph=True,
|
||||
uses_temporal=True,
|
||||
quality_score=0.95,
|
||||
)
|
||||
|
||||
def can_handle(self, request: dict[str, Any]) -> float:
|
||||
@@ -265,8 +268,9 @@ class TemporalArchaeologyStrategy:
|
||||
@property
|
||||
def capabilities(self) -> StrategyCapabilities:
|
||||
return StrategyCapabilities(
|
||||
supports_temporal_archaeology=True,
|
||||
supports_graph_navigation=True,
|
||||
uses_temporal=True,
|
||||
uses_graph=True,
|
||||
quality_score=0.5,
|
||||
)
|
||||
|
||||
def can_handle(self, request: dict[str, Any]) -> float:
|
||||
@@ -362,7 +366,8 @@ class PlanDecisionContextStrategy:
|
||||
@property
|
||||
def capabilities(self) -> StrategyCapabilities:
|
||||
return StrategyCapabilities(
|
||||
supports_temporal_archaeology=True,
|
||||
uses_temporal=True,
|
||||
quality_score=0.7,
|
||||
)
|
||||
|
||||
def can_handle(self, request: dict[str, Any]) -> float:
|
||||
|
||||
@@ -24,7 +24,6 @@ from __future__ import annotations
|
||||
|
||||
import re
|
||||
from collections.abc import Sequence
|
||||
from dataclasses import dataclass
|
||||
from threading import local
|
||||
from typing import TYPE_CHECKING, Any, ClassVar, Protocol, runtime_checkable
|
||||
|
||||
@@ -38,6 +37,9 @@ if TYPE_CHECKING:
|
||||
from cleveragents.domain.models.acms.crp import (
|
||||
ContextRequest,
|
||||
)
|
||||
from cleveragents.domain.models.acms.strategy import (
|
||||
StrategyCapabilities,
|
||||
)
|
||||
from cleveragents.domain.models.core.context_fragment import (
|
||||
ULID_PATTERN,
|
||||
ContextBudget,
|
||||
@@ -94,22 +96,6 @@ def _get_greedy_knapsack_packer_class() -> type:
|
||||
logger = structlog.get_logger(__name__)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Strategy capabilities (spec ~line 25167)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class StrategyCapabilities:
|
||||
"""Capabilities declared by a context strategy."""
|
||||
|
||||
supports_semantic_search: bool = False
|
||||
supports_graph_navigation: bool = False
|
||||
supports_temporal_archaeology: bool = False
|
||||
max_fragments: int | None = None
|
||||
quality_score: float = 1.0
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Context strategy protocol (spec ~line 25167)
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -179,7 +165,11 @@ class RelevanceStrategy:
|
||||
|
||||
@property
|
||||
def capabilities(self) -> StrategyCapabilities:
|
||||
return StrategyCapabilities(supports_semantic_search=True)
|
||||
return StrategyCapabilities(
|
||||
uses_vector=True,
|
||||
resource_types=("file", "snippet"),
|
||||
quality_score=0.8,
|
||||
)
|
||||
|
||||
def can_handle(self, request: dict[str, Any]) -> float:
|
||||
return 0.8 # general-purpose, high confidence
|
||||
@@ -211,7 +201,11 @@ class RecencyStrategy:
|
||||
|
||||
@property
|
||||
def capabilities(self) -> StrategyCapabilities:
|
||||
return StrategyCapabilities(supports_temporal_archaeology=True)
|
||||
return StrategyCapabilities(
|
||||
uses_temporal=True,
|
||||
resource_types=("file", "commit", "event"),
|
||||
quality_score=0.6,
|
||||
)
|
||||
|
||||
def can_handle(self, request: dict[str, Any]) -> float:
|
||||
return 0.6
|
||||
@@ -255,7 +249,11 @@ class TieredStrategy:
|
||||
|
||||
@property
|
||||
def capabilities(self) -> StrategyCapabilities:
|
||||
return StrategyCapabilities()
|
||||
return StrategyCapabilities(
|
||||
uses_text=True,
|
||||
resource_types=("file", "snippet", "summary"),
|
||||
quality_score=0.7,
|
||||
)
|
||||
|
||||
def can_handle(self, request: dict[str, Any]) -> float:
|
||||
return 0.7
|
||||
@@ -317,14 +315,8 @@ class SpecStrategyAdapter:
|
||||
|
||||
@property
|
||||
def capabilities(self) -> StrategyCapabilities:
|
||||
# Bridge: map spec StrategyCapabilities to pipeline StrategyCapabilities.
|
||||
spec_caps = self._spec_strategy.capabilities
|
||||
return StrategyCapabilities(
|
||||
supports_semantic_search=getattr(spec_caps, "uses_vector", False),
|
||||
supports_graph_navigation=getattr(spec_caps, "uses_graph", False),
|
||||
supports_temporal_archaeology=getattr(spec_caps, "uses_temporal", False),
|
||||
quality_score=getattr(spec_caps, "quality_score", 0.5),
|
||||
)
|
||||
# Return the spec strategy's domain-model StrategyCapabilities directly.
|
||||
return self._spec_strategy.capabilities
|
||||
|
||||
def can_handle(self, request: dict[str, Any]) -> float:
|
||||
"""Return the spec strategy's quality score as confidence."""
|
||||
|
||||
@@ -28,9 +28,11 @@ from collections.abc import Sequence
|
||||
from typing import Any
|
||||
|
||||
from cleveragents.application.services.acms_service import (
|
||||
StrategyCapabilities,
|
||||
_pack_budget,
|
||||
)
|
||||
from cleveragents.domain.models.acms.strategy import (
|
||||
StrategyCapabilities,
|
||||
)
|
||||
from cleveragents.domain.models.core.context_fragment import (
|
||||
ContextBudget,
|
||||
ContextFragment,
|
||||
@@ -75,7 +77,7 @@ class SimpleKeywordStrategy:
|
||||
|
||||
@property
|
||||
def capabilities(self) -> StrategyCapabilities:
|
||||
return StrategyCapabilities(supports_semantic_search=False)
|
||||
return StrategyCapabilities(uses_text=True, quality_score=0.3)
|
||||
|
||||
def can_handle(self, request: dict[str, Any]) -> float:
|
||||
"""Return 0.3 confidence — universal fallback."""
|
||||
@@ -169,7 +171,7 @@ class SemanticEmbeddingStrategy:
|
||||
|
||||
@property
|
||||
def capabilities(self) -> StrategyCapabilities:
|
||||
return StrategyCapabilities(supports_semantic_search=True)
|
||||
return StrategyCapabilities(uses_vector=True, uses_text=True, quality_score=0.6)
|
||||
|
||||
def can_handle(self, request: dict[str, Any]) -> float:
|
||||
"""Return 0.6 confidence when a query is present, else 0.1."""
|
||||
@@ -265,7 +267,7 @@ class BreadthDepthNavigatorStrategy:
|
||||
|
||||
@property
|
||||
def capabilities(self) -> StrategyCapabilities:
|
||||
return StrategyCapabilities(supports_graph_navigation=True)
|
||||
return StrategyCapabilities(uses_graph=True, quality_score=0.85)
|
||||
|
||||
def can_handle(self, request: dict[str, Any]) -> float:
|
||||
"""Return 0.85 when focus nodes are present, else 0.2."""
|
||||
|
||||
Reference in New Issue
Block a user