@phase2 @acms @context_strategies
Feature: Built-in Context Strategies Batch 1
  As a CleverAgents developer
  I want built-in context strategies
  So that the ACMS pipeline can rank fragments using different approaches

  # ===========================================================================
  # SimpleKeywordStrategy
  # ===========================================================================

  @simple_keyword
  Scenario: SimpleKeyword ranks by keyword match count
    Given a SimpleKeywordStrategy with query "async IO"
    And the following strategy fragments:
      | uko_node              | content                | score | tokens | depth |
      | project://app/io.py   | Use async IO pattern   | 0.5   | 20     | 3     |
      | project://app/main.py | Main entry point       | 0.8   | 15     | 3     |
      | project://app/net.py  | Async network handler  | 0.6   | 25     | 3     |
    And a strategy budget with max_tokens 1000 and reserved_tokens 0
    When I assemble with the SimpleKeywordStrategy
    Then the first result fragment should have uko_node "project://app/io.py"

  @simple_keyword
  Scenario: SimpleKeyword without query falls back to word density
    Given a SimpleKeywordStrategy without query
    And the following strategy fragments:
      | uko_node              | content                              | score | tokens | depth |
      | project://app/io.py   | io                                   | 0.5   | 10     | 3     |
      | project://app/main.py | Main entry point with many words here | 0.5  | 10     | 3     |
    And a strategy budget with max_tokens 1000 and reserved_tokens 0
    When I assemble with the SimpleKeywordStrategy
    Then 2 fragments should be returned by strategy

  @simple_keyword
  Scenario: SimpleKeyword returns empty for empty input
    Given a SimpleKeywordStrategy with query "test"
    And an empty strategy fragment list
    And a strategy budget with max_tokens 1000 and reserved_tokens 0
    When I assemble with the SimpleKeywordStrategy
    Then 0 fragments should be returned by strategy

  @simple_keyword
  Scenario: SimpleKeyword respects budget
    Given a SimpleKeywordStrategy with query "hello"
    And the following strategy fragments:
      | uko_node              | content     | score | tokens | depth |
      | project://app/a.py    | hello world | 0.9   | 100    | 3     |
      | project://app/b.py    | hello there | 0.7   | 100    | 3     |
      | project://app/c.py    | hello again | 0.5   | 100    | 3     |
    And a strategy budget with max_tokens 250 and reserved_tokens 0
    When I assemble with the SimpleKeywordStrategy
    Then 2 fragments should be returned by strategy

  @simple_keyword
  Scenario: SimpleKeyword can_handle returns 0.3
    Given a SimpleKeywordStrategy without query
    When I check can_handle on SimpleKeywordStrategy with query "test"
    Then the strategy confidence should be 0.3

  @simple_keyword
  Scenario: SimpleKeyword reports capabilities
    Given a SimpleKeywordStrategy without query
    Then the SimpleKeywordStrategy should not support semantic search
    And the SimpleKeywordStrategy name should be "simple-keyword"

  # ===========================================================================
  # SemanticEmbeddingStrategy
  # ===========================================================================

  @semantic_embedding
  Scenario: SemanticEmbedding ranks by word similarity
    Given a SemanticEmbeddingStrategy with query "database connection pool"
    And the following strategy 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 strategy budget with max_tokens 1000 and reserved_tokens 0
    When I assemble with the SemanticEmbeddingStrategy
    Then the first result fragment should have uko_node "project://app/db.py"

  @semantic_embedding
  Scenario: SemanticEmbedding filters below similarity threshold
    Given a SemanticEmbeddingStrategy with query "quantum computing"
    And the following strategy 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 strategy budget with max_tokens 1000 and reserved_tokens 0
    When I assemble with the SemanticEmbeddingStrategy
    Then 0 fragments should be returned by strategy

  @semantic_embedding
  Scenario: SemanticEmbedding without query falls back to relevance
    Given a SemanticEmbeddingStrategy without query
    And the following strategy 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 strategy budget with max_tokens 1000 and reserved_tokens 0
    When I assemble with the SemanticEmbeddingStrategy
    Then the first result fragment should have uko_node "project://app/b.py"

  @semantic_embedding
  Scenario: SemanticEmbedding can_handle returns 0.6 with query
    Given a SemanticEmbeddingStrategy without query
    When I check can_handle on SemanticEmbeddingStrategy with query "test"
    Then the strategy confidence should be 0.6

  @semantic_embedding
  Scenario: SemanticEmbedding can_handle returns 0.1 without query
    Given a SemanticEmbeddingStrategy without query
    When I check can_handle on SemanticEmbeddingStrategy without query
    Then the strategy confidence should be 0.1

  @semantic_embedding
  Scenario: SemanticEmbedding reports capabilities
    Given a SemanticEmbeddingStrategy without query
    Then the SemanticEmbeddingStrategy should support semantic search
    And the SemanticEmbeddingStrategy name should be "semantic-embedding"

  # ===========================================================================
  # BreadthDepthNavigatorStrategy
  # ===========================================================================

  @breadth_depth
  Scenario: BreadthDepthNavigator prioritises near focus nodes
    Given a BreadthDepthNavigatorStrategy with focus "project://app/io.py"
    And the following strategy 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 strategy budget with max_tokens 1000 and reserved_tokens 0
    When I assemble with the BreadthDepthNavigatorStrategy
    Then the first result fragment should have uko_node "project://app/io.py"

  @breadth_depth
  Scenario: BreadthDepthNavigator prefers higher depth near focus
    Given a BreadthDepthNavigatorStrategy with focus "project://app"
    And the following strategy fragments:
      | uko_node              | content | score | tokens | depth |
      | project://app/a.py    | alpha   | 0.5   | 10     | 9     |
      | project://app/b.py    | beta    | 0.5   | 10     | 1     |
    And a strategy budget with max_tokens 1000 and reserved_tokens 0
    When I assemble with the BreadthDepthNavigatorStrategy
    Then the first result fragment should have uko_node "project://app/a.py"

  @breadth_depth
  Scenario: BreadthDepthNavigator without focus falls back to depth+relevance
    Given a BreadthDepthNavigatorStrategy without focus
    And the following strategy fragments:
      | uko_node              | content | score | tokens | depth |
      | project://app/a.py    | alpha   | 0.5   | 10     | 9     |
      | project://app/b.py    | beta    | 0.9   | 10     | 2     |
    And a strategy budget with max_tokens 1000 and reserved_tokens 0
    When I assemble with the BreadthDepthNavigatorStrategy
    Then the first result fragment should have uko_node "project://app/a.py"

  @breadth_depth
  Scenario: BreadthDepthNavigator can_handle returns 0.85 with focus
    Given a BreadthDepthNavigatorStrategy without focus
    When I check can_handle on BreadthDepthNavigator with focus
    Then the strategy confidence should be 0.85

  @breadth_depth
  Scenario: BreadthDepthNavigator can_handle returns 0.2 without focus
    Given a BreadthDepthNavigatorStrategy without focus
    When I check can_handle on BreadthDepthNavigator without focus
    Then the strategy confidence should be 0.2

  @breadth_depth
  Scenario: BreadthDepthNavigator reports capabilities
    Given a BreadthDepthNavigatorStrategy without focus
    Then the BreadthDepthNavigatorStrategy should support graph navigation
    And the BreadthDepthNavigatorStrategy name should be "breadth-depth-navigator"

  @breadth_depth
  Scenario: BreadthDepthNavigator respects budget
    Given a BreadthDepthNavigatorStrategy with focus "project://app"
    And the following strategy fragments:
      | uko_node              | content | score | tokens | depth |
      | project://app/a.py    | alpha   | 0.9   | 100    | 5     |
      | project://app/b.py    | beta    | 0.7   | 100    | 5     |
      | project://app/c.py    | gamma   | 0.5   | 100    | 5     |
    And a strategy budget with max_tokens 250 and reserved_tokens 0
    When I assemble with the BreadthDepthNavigatorStrategy
    Then 2 fragments should be returned by strategy

  @breadth_depth
  Scenario: BreadthDepthNavigator returns empty for empty input
    Given a BreadthDepthNavigatorStrategy with focus "project://app"
    And an empty strategy fragment list
    And a strategy budget with max_tokens 1000 and reserved_tokens 0
    When I assemble with the BreadthDepthNavigatorStrategy
    Then 0 fragments should be returned by strategy

  @breadth_depth
  Scenario: BreadthDepthNavigator can_handle accepts focus as string
    Given a BreadthDepthNavigatorStrategy without focus
    When I check can_handle on BreadthDepthNavigator with string focus
    Then the strategy confidence should be 0.85

  @semantic_embedding
  Scenario: SemanticEmbedding returns empty for empty input
    Given a SemanticEmbeddingStrategy with query "test"
    And an empty strategy fragment list
    And a strategy budget with max_tokens 1000 and reserved_tokens 0
    When I assemble with the SemanticEmbeddingStrategy
    Then 0 fragments should be returned by strategy

  @semantic_embedding
  Scenario: SemanticEmbedding handles fragment with empty content
    Given a SemanticEmbeddingStrategy with query "test"
    And the following strategy fragments:
      | uko_node            | content | score | tokens | depth |
      | project://app/a.py  |         | 0.5   | 10     | 3     |
    And a strategy budget with max_tokens 1000 and reserved_tokens 0
    When I assemble with the SemanticEmbeddingStrategy
    Then 0 fragments should be returned by strategy

  # ===========================================================================
  # explain() coverage
  # ===========================================================================

  @simple_keyword
  Scenario: SimpleKeyword explain returns description
    Given a SimpleKeywordStrategy without query
    Then the SimpleKeywordStrategy explain should contain "keyword"

  @semantic_embedding
  Scenario: SemanticEmbedding explain returns description
    Given a SemanticEmbeddingStrategy without query
    Then the SemanticEmbeddingStrategy explain should contain "semantic"

  @breadth_depth
  Scenario: BreadthDepthNavigator explain returns description
    Given a BreadthDepthNavigatorStrategy without focus
    Then the BreadthDepthNavigatorStrategy explain should contain "hierarchy"

  # ===========================================================================
  # Pipeline Registration
  # ===========================================================================

  @registration
  Scenario: Register SimpleKeywordStrategy with pipeline
    Given an ACMS pipeline for strategy tests
    When I register SimpleKeywordStrategy with the pipeline
    Then the pipeline should have strategy "simple-keyword"

  @registration
  Scenario: Register all three strategies with pipeline
    Given an ACMS pipeline for strategy tests
    When I register all batch 1 strategies with the pipeline
    Then the pipeline should have strategy "simple-keyword"
    And the pipeline should have strategy "semantic-embedding"
    And the pipeline should have strategy "breadth-depth-navigator"
