@phase3 @acms @advanced_context_strategies Feature: Advanced Context Strategies Integration Tests As a CleverAgents developer I want advanced context strategies for semantic search, relevance scoring, and adaptive selection So that the ACMS pipeline can intelligently select and combine strategies # =========================================================================== # Semantic Search Strategy (with FakeEmbeddings) # =========================================================================== @semantic_search Scenario: Semantic search strategy ranks by embedding similarity Given a semantic search strategy with FakeEmbeddings And the following context fragments: | uko_node | content | score | tokens | depth | | project://app/db.py | Database connection pool manager | 0.5 | 20 | 3 | | project://app/io.py | File input output handler | 0.8 | 15 | 3 | | project://app/sql.py | SQL database query executor | 0.6 | 25 | 3 | And a context budget with max_tokens 1000 and reserved_tokens 0 When I search with query "database connection" Then the first result should have uko_node "project://app/db.py" And the result should have 2 fragments @semantic_search Scenario: Semantic search filters low-similarity results Given a semantic search strategy with FakeEmbeddings And the following context fragments: | uko_node | content | score | tokens | depth | | project://app/db.py | database handler | 0.9 | 20 | 3 | | project://app/io.py | file io module | 0.8 | 15 | 3 | And a context budget with max_tokens 1000 and reserved_tokens 0 When I search with query "quantum computing" Then 0 fragments should be returned @semantic_search Scenario: Semantic search respects token budget Given a semantic search strategy with FakeEmbeddings And the following context fragments: | uko_node | content | score | tokens | depth | | project://app/a.py | database | 0.9 | 100 | 3 | | project://app/b.py | database | 0.8 | 100 | 3 | | project://app/c.py | database | 0.7 | 100 | 3 | And a context budget with max_tokens 250 and reserved_tokens 0 When I search with query "database" Then 2 fragments should be returned # =========================================================================== # Relevance Scoring Strategy # =========================================================================== @relevance_scoring Scenario: Relevance scoring strategy ranks by relevance score Given a relevance scoring strategy And the following context fragments: | uko_node | content | score | tokens | depth | | project://app/a.py | alpha | 0.3 | 10 | 3 | | project://app/b.py | beta | 0.9 | 10 | 3 | | project://app/c.py | gamma | 0.6 | 10 | 3 | And a context budget with max_tokens 1000 and reserved_tokens 0 When I assemble with relevance scoring Then the first result should have uko_node "project://app/b.py" And the second result should have uko_node "project://app/c.py" And the third result should have uko_node "project://app/a.py" @relevance_scoring Scenario: Relevance scoring respects budget Given a relevance scoring strategy And the following context fragments: | uko_node | content | score | tokens | depth | | project://app/a.py | alpha | 0.9 | 100 | 3 | | project://app/b.py | beta | 0.8 | 100 | 3 | | project://app/c.py | gamma | 0.7 | 100 | 3 | And a context budget with max_tokens 250 and reserved_tokens 0 When I assemble with relevance scoring Then 2 fragments should be returned @relevance_scoring Scenario: Relevance scoring handles empty input Given a relevance scoring strategy And an empty context fragment list And a context budget with max_tokens 1000 and reserved_tokens 0 When I assemble with relevance scoring Then 0 fragments should be returned # =========================================================================== # Adaptive Context Strategy Selector # =========================================================================== @adaptive_selector Scenario: Adaptive selector chooses best strategy for query Given an adaptive context strategy selector And the following context fragments: | uko_node | content | score | tokens | depth | | project://app/db.py | Database connection pool manager | 0.5 | 20 | 3 | | project://app/io.py | File input output handler | 0.8 | 15 | 3 | | project://app/sql.py | SQL database query executor | 0.6 | 25 | 3 | And a context budget with max_tokens 1000 and reserved_tokens 0 When I select strategy for query "database connection" Then the selected strategy should be "semantic-embedding" @adaptive_selector Scenario: Adaptive selector falls back to relevance for no query Given an adaptive context strategy selector And the following context fragments: | uko_node | content | score | tokens | depth | | project://app/a.py | alpha | 0.3 | 10 | 3 | | project://app/b.py | beta | 0.9 | 10 | 3 | And a context budget with max_tokens 1000 and reserved_tokens 0 When I select strategy without query Then the selected strategy should be "relevance-scoring" @adaptive_selector Scenario: Adaptive selector chooses graph navigation for focus nodes Given an adaptive context strategy selector And the following context fragments: | uko_node | content | score | tokens | depth | | project://app/io.py | io module | 0.5 | 20 | 5 | | project://app/main.py | main entry | 0.9 | 15 | 3 | | project://other/lib.py | library | 0.7 | 25 | 9 | And a context budget with max_tokens 1000 and reserved_tokens 0 When I select strategy with focus "project://app" Then the selected strategy should be "breadth-depth-navigator" # =========================================================================== # Context Fusion Strategy # =========================================================================== @context_fusion Scenario: Context fusion combines results from multiple strategies Given a context fusion strategy with strategies "semantic-embedding,relevance-scoring" And the following context fragments: | uko_node | content | score | tokens | depth | | project://app/db.py | Database connection pool manager | 0.5 | 20 | 3 | | project://app/io.py | File input output handler | 0.8 | 15 | 3 | | project://app/sql.py | SQL database query executor | 0.6 | 25 | 3 | And a context budget with max_tokens 1000 and reserved_tokens 0 When I fuse with query "database" Then at least 2 fragments should be returned by fusion And the result should contain fragments from multiple strategies @context_fusion Scenario: Context fusion respects budget across strategies Given a context fusion strategy with strategies "semantic-embedding,relevance-scoring" And the following context fragments: | uko_node | content | score | tokens | depth | | project://app/a.py | database | 0.9 | 100 | 3 | | project://app/b.py | database | 0.8 | 100 | 3 | | project://app/c.py | database | 0.7 | 100 | 3 | And a context budget with max_tokens 250 and reserved_tokens 0 When I fuse with query "database" Then the total tokens should not exceed 250 @context_fusion Scenario: Context fusion deduplicates results Given a context fusion strategy with strategies "semantic-embedding,relevance-scoring" And the following context fragments: | uko_node | content | score | tokens | depth | | project://app/a.py | database | 0.9 | 100 | 3 | | project://app/b.py | database | 0.8 | 100 | 3 | And a context budget with max_tokens 1000 and reserved_tokens 0 When I fuse with query "database" Then each fragment should appear only once in results # =========================================================================== # YAML Strategy Configuration # =========================================================================== @yaml_config Scenario: Load semantic search strategy from YAML Given a YAML policy with semantic search configuration When I load the strategy from YAML Then the loaded strategy type should be "semantic-embedding" And the strategy should have min_similarity configured @yaml_config Scenario: Load relevance scoring strategy from YAML Given a YAML policy with relevance scoring configuration When I load the strategy from YAML Then the loaded strategy type should be "relevance-scoring" @yaml_config Scenario: Load adaptive selector from YAML Given a YAML policy with adaptive selector configuration When I load the strategy from YAML Then the loaded strategy type should be "adaptive-selector" And the strategy should have fallback strategy configured @yaml_config Scenario: Load context fusion from YAML Given a YAML policy with context fusion configuration When I load the strategy from YAML Then the loaded strategy type should be "context-fusion" And the strategy should have multiple strategies configured @yaml_config Scenario: YAML configuration with custom parameters Given a YAML policy with custom strategy parameters When I load the strategy from YAML Then the strategy should respect custom parameters # =========================================================================== # Integration with ContextAssembler # =========================================================================== @integration Scenario: Advanced strategies integrate with ContextAssembler Given a ContextAssembler with advanced strategies registered And the following context fragments: | uko_node | content | score | tokens | depth | | project://app/db.py | Database connection pool manager | 0.5 | 20 | 3 | | project://app/io.py | File input output handler | 0.8 | 15 | 3 | | project://app/sql.py | SQL database query executor | 0.6 | 25 | 3 | And a context budget with max_tokens 1000 and reserved_tokens 0 When I assemble context with query "database" Then the assembler should select an appropriate strategy And the result should be properly ranked @integration Scenario: ContextAssembler respects strategy priority Given a ContextAssembler with multiple strategies registered And the following context fragments: | uko_node | content | score | tokens | depth | | project://app/a.py | alpha | 0.5 | 10 | 3 | | project://app/b.py | beta | 0.9 | 10 | 3 | And a context budget with max_tokens 1000 and reserved_tokens 0 When I assemble context with query "test" Then the highest-confidence strategy should be selected @integration Scenario: ContextAssembler handles strategy fallback Given a ContextAssembler with advanced strategies registered And the following context fragments: | uko_node | content | score | tokens | depth | | project://app/a.py | alpha | 0.5 | 10 | 3 | And a context budget with max_tokens 1000 and reserved_tokens 0 When I assemble context with unsupported request Then the assembler should fall back to default strategy # =========================================================================== # Error Handling and Edge Cases # =========================================================================== @error_handling Scenario: Semantic search handles empty query Given a semantic search strategy with FakeEmbeddings And the following context fragments: | uko_node | content | score | tokens | depth | | project://app/a.py | alpha | 0.5 | 10 | 3 | And a context budget with max_tokens 1000 and reserved_tokens 0 When I search with empty query Then the strategy should fall back to relevance ordering @error_handling Scenario: Adaptive selector handles invalid request Given an adaptive context strategy selector And the following context fragments: | uko_node | content | score | tokens | depth | | project://app/a.py | alpha | 0.5 | 10 | 3 | And a context budget with max_tokens 1000 and reserved_tokens 0 When I select strategy with invalid request Then the selector should return a valid strategy @error_handling Scenario: Context fusion handles strategy failure Given a context fusion strategy with strategies "semantic-embedding,relevance-scoring" And the following context fragments: | uko_node | content | score | tokens | depth | | project://app/a.py | alpha | 0.5 | 10 | 3 | And a context budget with max_tokens 1000 and reserved_tokens 0 When one strategy fails during fusion Then the fusion should continue with remaining strategies @error_handling Scenario: YAML configuration handles missing parameters Given a YAML policy with incomplete strategy configuration When I load the strategy from YAML Then the strategy should use default parameters