feat(context): implement PriorityContextStrategy with configurable priority scoring
Implements PriorityContextStrategy (issue #9997) with: - PriorityRule dataclass with field, matcher, and score attributes - Default role-based priority rules: system > tool > user > assistant - Recency decay scoring using exponential half-life decay - Explicit priority tag boost via metadata['priority_tag'] - Custom scoring function injection via score_fn parameter - Custom PriorityRule list injection via rules parameter - Greedy selection of highest-scoring messages within token budget - Registration in ACMS pipeline under key 'priority_context' - 18 BDD scenarios covering all acceptance criteria (100% coverage) ISSUES CLOSED: #9997
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
@phase2 @acms @context_strategies @priority_context
|
||||
Feature: PriorityContextStrategy with configurable priority scoring
|
||||
As a CleverAgents developer
|
||||
I want a priority-based context strategy
|
||||
So that high-priority messages are always retained when the context window must be trimmed
|
||||
|
||||
@priority_context_protocol
|
||||
Scenario: PriorityContextStrategy satisfies ContextStrategy protocol
|
||||
Given a PriorityContextStrategy with default rules
|
||||
Then the PriorityContextStrategy should satisfy the ContextStrategy protocol
|
||||
And the PriorityContextStrategy name should be "priority_context"
|
||||
|
||||
@priority_context_protocol
|
||||
Scenario: PriorityContextStrategy reports capabilities
|
||||
Given a PriorityContextStrategy with default rules
|
||||
Then the PriorityContextStrategy capabilities should be a StrategyCapabilities instance
|
||||
|
||||
@priority_context_protocol
|
||||
Scenario: PriorityContextStrategy explain returns non-empty description
|
||||
Given a PriorityContextStrategy with default rules
|
||||
Then the PriorityContextStrategy explain should contain "priority"
|
||||
|
||||
@priority_context_can_handle
|
||||
Scenario: PriorityContextStrategy can_handle returns 0.75 with any request
|
||||
Given a PriorityContextStrategy with default rules
|
||||
When I check can_handle on PriorityContextStrategy with query "test"
|
||||
Then the strategy confidence should be 0.75
|
||||
|
||||
@priority_context_can_handle
|
||||
Scenario: PriorityContextStrategy can_handle returns 0.75 without query
|
||||
Given a PriorityContextStrategy with default rules
|
||||
When I check can_handle on PriorityContextStrategy without query
|
||||
Then the strategy confidence should be 0.75
|
||||
|
||||
@priority_context_role
|
||||
Scenario: System role fragments are ranked highest by default
|
||||
Given a PriorityContextStrategy with default rules
|
||||
And the following priority strategy fragments:
|
||||
| uko_node | content | score | tokens | depth | role |
|
||||
| project://app/a.py | assistant message | 0.9 | 20 | 3 | assistant |
|
||||
| project://app/b.py | system instruction | 0.5 | 20 | 3 | system |
|
||||
| project://app/c.py | user request | 0.7 | 20 | 3 | user |
|
||||
| project://app/d.py | tool result | 0.6 | 20 | 3 | tool |
|
||||
And a strategy budget with max_tokens 1000 and reserved_tokens 0
|
||||
When I assemble with the PriorityContextStrategy
|
||||
Then the first result fragment should have uko_node "project://app/b.py"
|
||||
|
||||
@priority_context_role
|
||||
Scenario: Tool role fragments are ranked above user and assistant
|
||||
Given a PriorityContextStrategy with default rules
|
||||
And the following priority strategy fragments:
|
||||
| uko_node | content | score | tokens | depth | role |
|
||||
| project://app/a.py | assistant message | 0.9 | 20 | 3 | assistant |
|
||||
| project://app/b.py | user request | 0.8 | 20 | 3 | user |
|
||||
| project://app/c.py | tool result | 0.5 | 20 | 3 | tool |
|
||||
And a strategy budget with max_tokens 1000 and reserved_tokens 0
|
||||
When I assemble with the PriorityContextStrategy
|
||||
Then the first result fragment should have uko_node "project://app/c.py"
|
||||
|
||||
@priority_context_role
|
||||
Scenario: User role fragments are ranked above assistant
|
||||
Given a PriorityContextStrategy with default rules
|
||||
And the following priority strategy fragments:
|
||||
| uko_node | content | score | tokens | depth | role |
|
||||
| project://app/a.py | assistant message | 0.9 | 20 | 3 | assistant |
|
||||
| project://app/b.py | user request | 0.5 | 20 | 3 | user |
|
||||
And a strategy budget with max_tokens 1000 and reserved_tokens 0
|
||||
When I assemble with the PriorityContextStrategy
|
||||
Then the first result fragment should have uko_node "project://app/b.py"
|
||||
|
||||
@priority_context_tag
|
||||
Scenario: Fragments with priority tag are boosted above role-based score
|
||||
Given a PriorityContextStrategy with default rules
|
||||
And the following priority strategy fragments with tags:
|
||||
| uko_node | content | score | tokens | depth | role | priority_tag |
|
||||
| project://app/a.py | system instruction | 0.5 | 20 | 3 | system | |
|
||||
| project://app/b.py | user request | 0.5 | 20 | 3 | user | high |
|
||||
And a strategy budget with max_tokens 1000 and reserved_tokens 0
|
||||
When I assemble with the PriorityContextStrategy
|
||||
Then the first result fragment should have uko_node "project://app/b.py"
|
||||
|
||||
@priority_context_tag
|
||||
Scenario: Fragments without priority tag are not boosted
|
||||
Given a PriorityContextStrategy with default rules
|
||||
And the following priority strategy fragments with tags:
|
||||
| uko_node | content | score | tokens | depth | role | priority_tag |
|
||||
| project://app/a.py | system instruction | 0.9 | 20 | 3 | system | |
|
||||
| project://app/b.py | user request | 0.5 | 20 | 3 | user | |
|
||||
And a strategy budget with max_tokens 1000 and reserved_tokens 0
|
||||
When I assemble with the PriorityContextStrategy
|
||||
Then the first result fragment should have uko_node "project://app/a.py"
|
||||
|
||||
@priority_context_budget
|
||||
Scenario: PriorityContextStrategy respects token budget
|
||||
Given a PriorityContextStrategy with default rules
|
||||
And the following priority strategy fragments:
|
||||
| uko_node | content | score | tokens | depth | role |
|
||||
| project://app/a.py | system instruction one | 0.9 | 100 | 3 | system |
|
||||
| project://app/b.py | system instruction two | 0.8 | 100 | 3 | system |
|
||||
| project://app/c.py | system instruction three | 0.7 | 100 | 3 | system |
|
||||
And a strategy budget with max_tokens 250 and reserved_tokens 0
|
||||
When I assemble with the PriorityContextStrategy
|
||||
Then 2 fragments should be returned by priority strategy
|
||||
|
||||
@priority_context_budget
|
||||
Scenario: PriorityContextStrategy returns empty for empty input
|
||||
Given a PriorityContextStrategy with default rules
|
||||
And an empty priority strategy fragment list
|
||||
And a strategy budget with max_tokens 1000 and reserved_tokens 0
|
||||
When I assemble with the PriorityContextStrategy
|
||||
Then 0 fragments should be returned by priority strategy
|
||||
|
||||
@priority_context_custom_fn
|
||||
Scenario: Custom scoring function overrides default scoring
|
||||
Given a PriorityContextStrategy with a custom score function that boosts depth
|
||||
And the following priority strategy fragments:
|
||||
| uko_node | content | score | tokens | depth | role |
|
||||
| project://app/a.py | system instruction | 0.9 | 20 | 1 | system |
|
||||
| project://app/b.py | user request | 0.5 | 20 | 9 | user |
|
||||
And a strategy budget with max_tokens 1000 and reserved_tokens 0
|
||||
When I assemble with the PriorityContextStrategy
|
||||
Then the first result fragment should have uko_node "project://app/b.py"
|
||||
|
||||
@priority_context_custom_fn
|
||||
Scenario: Custom scoring function receives fragment and returns float
|
||||
Given a PriorityContextStrategy with a custom score function that returns constant 1.0
|
||||
And the following priority strategy fragments:
|
||||
| uko_node | content | score | tokens | depth | role |
|
||||
| project://app/a.py | system instruction | 0.9 | 20 | 3 | system |
|
||||
| project://app/b.py | user request | 0.5 | 20 | 3 | user |
|
||||
And a strategy budget with max_tokens 1000 and reserved_tokens 0
|
||||
When I assemble with the PriorityContextStrategy
|
||||
Then 2 fragments should be returned by priority strategy
|
||||
|
||||
@priority_context_rule
|
||||
Scenario: PriorityRule has field, matcher, and score attributes
|
||||
Given a PriorityRule with field "role" matcher "system" and score 1.0
|
||||
Then the PriorityRule field should be "role"
|
||||
And the PriorityRule matcher should be "system"
|
||||
And the PriorityRule score should be 1.0
|
||||
|
||||
@priority_context_rule
|
||||
Scenario: PriorityContextStrategy accepts custom PriorityRule list
|
||||
Given a PriorityContextStrategy with custom rules boosting "tool" role to 2.0
|
||||
And the following priority strategy fragments:
|
||||
| uko_node | content | score | tokens | depth | role |
|
||||
| project://app/a.py | system instruction | 0.9 | 20 | 3 | system |
|
||||
| project://app/b.py | tool result | 0.5 | 20 | 3 | tool |
|
||||
And a strategy budget with max_tokens 1000 and reserved_tokens 0
|
||||
When I assemble with the PriorityContextStrategy
|
||||
Then the first result fragment should have uko_node "project://app/b.py"
|
||||
|
||||
@priority_context_registry
|
||||
Scenario: PriorityContextStrategy is registered in plugin registry under "priority_context"
|
||||
Given an ACMS pipeline for strategy tests
|
||||
When I register PriorityContextStrategy with the pipeline
|
||||
Then the pipeline should have strategy "priority_context"
|
||||
|
||||
@priority_context_recency
|
||||
Scenario: More recent fragments score higher with recency decay rule
|
||||
Given a PriorityContextStrategy with default rules
|
||||
And the following priority strategy fragments with recency:
|
||||
| uko_node | content | score | tokens | depth | role | days_old |
|
||||
| project://app/a.py | old system instruction | 0.9 | 20 | 3 | user | 30 |
|
||||
| project://app/b.py | recent user request | 0.5 | 20 | 3 | user | 0 |
|
||||
And a strategy budget with max_tokens 1000 and reserved_tokens 0
|
||||
When I assemble with the PriorityContextStrategy
|
||||
Then the first result fragment should have uko_node "project://app/b.py"
|
||||
Reference in New Issue
Block a user