Description
ContextService::inject_semantic_recall (service.rs:257) creates a recall message with Role::User when the tiered-retrieval path is active:
Some(Message::from_legacy(
Role::User,
format!("{RECALL_PREFIX}{recalled_text}"),
))
However remove_recall_messages delegates to remove_by_part_or_prefix (service.rs:1360–1368), which only removes messages where m.role == Role::System:
messages.retain(|m| {
if m.role != Role::System {
return true; // User-role recall is never removed
}
...
});
This means every call to inject_semantic_recall with tiered retrieval enabled inserts a new Role::User recall message that is never cleaned up by remove_recall_messages, causing recall messages to accumulate turn over turn.
Reproduction Steps
- Enable
tiered_retrieval_config.enabled = true in config.
- Call
ContextService::inject_semantic_recall multiple times on successive turns.
- Inspect
window.messages: observe multiple Role::User messages starting with RECALL_PREFIX accumulating.
Expected Behavior
Each call to inject_semantic_recall should first remove any existing recall message (regardless of role) and then insert at most one.
Actual Behavior
Role::User recall messages from the tiered-retrieval path are never removed; they accumulate across turns.
Fix Candidate
remove_by_part_or_prefix should also remove Role::User messages whose content starts with RECALL_PREFIX, or inject_semantic_recall should use Role::System consistently with the ContextAssembler::gather path.
Environment
- Commit: c9ff16a
- Crate: zeph-agent-context, service.rs:203, service.rs:1355
- Feature: tiered_retrieval
Description
ContextService::inject_semantic_recall(service.rs:257) creates a recall message withRole::Userwhen the tiered-retrieval path is active:However
remove_recall_messagesdelegates toremove_by_part_or_prefix(service.rs:1360–1368), which only removes messages wherem.role == Role::System:This means every call to
inject_semantic_recallwith tiered retrieval enabled inserts a newRole::Userrecall message that is never cleaned up byremove_recall_messages, causing recall messages to accumulate turn over turn.Reproduction Steps
tiered_retrieval_config.enabled = truein config.ContextService::inject_semantic_recallmultiple times on successive turns.window.messages: observe multipleRole::Usermessages starting withRECALL_PREFIXaccumulating.Expected Behavior
Each call to
inject_semantic_recallshould first remove any existing recall message (regardless of role) and then insert at most one.Actual Behavior
Role::User recall messages from the tiered-retrieval path are never removed; they accumulate across turns.
Fix Candidate
remove_by_part_or_prefixshould also removeRole::Usermessages whose content starts withRECALL_PREFIX, orinject_semantic_recallshould useRole::Systemconsistently with theContextAssembler::gatherpath.Environment