@phase2 @acms @context_fragment_models
Feature: ScoredFragment and ContextFragment pipeline models
  As a CleverAgents developer
  I want pipeline-specific fragment models with scoring and deduplication
  So that the ACMS context assembly pipeline can rank, deduplicate, and pack fragments

  # ---------------------------------------------------------------------------
  # ScoredFragment — Construction
  # ---------------------------------------------------------------------------

  @scored_fragment
  Scenario: Create a ScoredFragment with required fields
    Given a context fragment with uko_node "project://app/main.py" and content "hello" and token_count 10
    When I create a scored fragment with composite_score 0.85
    Then the scored fragment composite_score should be 0.85
    And the scored fragment rank should be 0
    And the scored fragment score_breakdown should be empty
    And the scored fragment uko_node should be "project://app/main.py"
    And the scored fragment detail_depth should be 0
    And the scored fragment token_count should be 10

  @scored_fragment
  Scenario: Create a ScoredFragment with all fields
    Given a context fragment with uko_node "project://app/io.py" and content "async IO" and token_count 50
    When I create a scored fragment with composite_score 0.92 and rank 1 and breakdown:
      | component   | score |
      | relevance   | 0.9   |
      | hierarchy   | 0.8   |
      | recency     | 0.95  |
    Then the scored fragment composite_score should be 0.92
    And the scored fragment rank should be 1
    And the scored fragment breakdown "relevance" should be 0.9
    And the scored fragment breakdown "hierarchy" should be 0.8
    And the scored fragment breakdown "recency" should be 0.95

  @scored_fragment
  Scenario: Create a ScoredFragment from relevance factory
    Given a context fragment with uko_node "project://app/util.py" and content "utils" and token_count 20 and relevance 0.75
    When I create a scored fragment from relevance
    Then the scored fragment composite_score should be 0.75
    And the scored fragment breakdown "relevance" should be 0.75
    And the scored fragment rank should be 0

  @scored_fragment
  Scenario: Create a ScoredFragment from fragment factory
    Given a context fragment with uko_node "project://app/core.py" and content "core" and token_count 30
    When I create a scored fragment from factory with score 0.6 and rank 3
    Then the scored fragment composite_score should be 0.6
    And the scored fragment rank should be 3

  # ---------------------------------------------------------------------------
  # ScoredFragment — Equality and Hashing
  # ---------------------------------------------------------------------------

  @scored_fragment @equality
  Scenario: ScoredFragments with same uko_node and detail_depth are equal
    Given two scored fragments with uko_node "project://app/main.py" and detail_depth 3
    Then the two scored fragments should be equal
    And the two scored fragments should have the same hash

  @scored_fragment @equality
  Scenario: ScoredFragments with different uko_node are not equal
    Given a scored fragment with uko_node "project://app/main.py" and detail_depth 3
    And another scored fragment with uko_node "project://app/other.py" and detail_depth 3
    Then the two scored fragments should not be equal

  @scored_fragment @equality
  Scenario: ScoredFragments with different detail_depth are not equal
    Given a scored fragment with uko_node "project://app/main.py" and detail_depth 3
    And another scored fragment with uko_node "project://app/main.py" and detail_depth 5
    Then the two scored fragments should not be equal

  @scored_fragment @equality
  Scenario: ScoredFragments can be deduplicated via set
    Given three scored fragments where two share uko_node "project://app/main.py" detail_depth 3
    When I add them to a set
    Then the set should contain 2 unique scored fragments

  @scored_fragment @equality
  Scenario: ScoredFragments with same identity but different scores are equal
    Given a scored fragment with uko_node "project://app/main.py" and detail_depth 2 and score 0.5
    And another scored fragment with uko_node "project://app/main.py" and detail_depth 2 and score 0.9
    Then the two scored fragments should be equal
    And the two scored fragments should have the same hash

  # ---------------------------------------------------------------------------
  # ScoredFragment — Immutability
  # ---------------------------------------------------------------------------

  @scored_fragment @immutability
  Scenario: ScoredFragment is frozen
    Given a context fragment with uko_node "project://app/main.py" and content "hello" and token_count 10
    When I create a scored fragment with composite_score 0.85
    Then modifying the scored fragment composite_score should raise an error

  # ---------------------------------------------------------------------------
  # ScoredFragment — Validation
  # ---------------------------------------------------------------------------

  @scored_fragment @validation
  Scenario: Invalid composite_score above 1.0 rejected
    Given a context fragment with uko_node "project://app/main.py" and content "hello" and token_count 10
    When I create a scored fragment with composite_score 1.5
    Then a validation error should be raised

  @scored_fragment @validation
  Scenario: Invalid composite_score below 0.0 rejected
    Given a context fragment with uko_node "project://app/main.py" and content "hello" and token_count 10
    When I create a scored fragment with composite_score -0.1
    Then a validation error should be raised

  @scored_fragment @validation
  Scenario: Invalid score_breakdown component rejected
    Given a context fragment with uko_node "project://app/main.py" and content "hello" and token_count 10
    When I create a scored fragment with an invalid breakdown component 1.5
    Then a validation error should be raised

  @scored_fragment @validation
  Scenario: Negative rank rejected
    Given a context fragment with uko_node "project://app/main.py" and content "hello" and token_count 10
    When I create a scored fragment with composite_score 0.5 and rank -1
    Then a validation error should be raised

  # ---------------------------------------------------------------------------
  # ContextFragment — strategy_source field
  # ---------------------------------------------------------------------------

  @context_fragment @strategy_source
  Scenario: ContextFragment has strategy_source field with default
    Given a context fragment with uko_node "project://app/main.py" and content "hello" and token_count 10
    Then the fragment strategy_source should be empty

  @context_fragment @strategy_source
  Scenario: ContextFragment strategy_source can be set
    Given a context fragment with uko_node "project://app/main.py" and content "hello" and token_count 10 and strategy_source "keyword-search"
    Then the fragment strategy_source should be "keyword-search"
