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:
2026-04-19 13:34:56 +00:00
committed by cleveragents-auto
parent 5e71221f61
commit 49ce9069be
3 changed files with 754 additions and 0 deletions
+168
View File
@@ -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"