use std::collections::{HashMap, HashSet};
use zeph_llm::provider::{Message, MessagePart};
use zeph_memory::TokenCounter;
#[derive(Debug, Clone)]
pub(crate) struct BlockScore {
pub(crate) msg_index: usize,
pub(crate) relevance: f32,
pub(crate) redundancy: f32,
pub(crate) mig: f32,
}
static STOP_WORDS: std::sync::LazyLock<HashSet<&'static str>> = std::sync::LazyLock::new(|| {
[
"fn", "pub", "let", "use", "mod", "impl", "struct", "enum", "trait", "type", "for", "if",
"else", "match", "return", "self", "super", "crate", "true", "false", "mut", "ref",
"where", "in", "as", "const", "static", "extern", "unsafe", "async", "await", "move",
"box", "dyn", "loop", "while", "break", "continue", "yield", "do", "try", "the", "a", "an",
"is", "are", "was", "be", "to", "of", "and", "or", "not", "with", "from", "by", "at", "on",
"in", "it", "this", "that", "have", "has", "had", "cargo", "rustc", "warning", "error",
"note", "help", "running",
]
.into_iter()
.collect()
});
fn tokenize(text: &str) -> Vec<String> {
text.split(|c: char| !c.is_alphanumeric() && c != '_')
.filter(|t| t.len() >= 3)
.map(str::to_lowercase)
.filter(|t| !STOP_WORDS.contains(t.as_str()))
.collect()
}
#[allow(clippy::cast_precision_loss)]
fn term_frequencies(tokens: &[String]) -> HashMap<String, f32> {
let mut counts: HashMap<String, usize> = HashMap::new();
for t in tokens {
*counts.entry(t.clone()).or_insert(0) += 1;
}
let total = tokens.len().max(1) as f32;
counts
.into_iter()
.map(|(k, v)| (k, v as f32 / total))
.collect()
}
fn tf_weighted_similarity(tf_a: &HashMap<String, f32>, tf_b: &HashMap<String, f32>) -> f32 {
let mut intersection = 0.0_f32;
let mut union = 0.0_f32;
for (term, freq_a) in tf_a {
if let Some(freq_b) = tf_b.get(term) {
intersection += freq_a.min(*freq_b);
}
union += *freq_a;
}
for (term, freq_b) in tf_b {
if !tf_a.contains_key(term) {
union += *freq_b;
}
}
if union == 0.0 {
0.0
} else {
intersection / union
}
}
pub(crate) fn extract_scorable_text(msg: &Message) -> String {
let mut parts_text = String::new();
for part in &msg.parts {
match part {
MessagePart::ToolOutput {
body, tool_name, ..
} => {
parts_text.push_str(tool_name);
parts_text.push(' ');
parts_text.push_str(body);
parts_text.push(' ');
}
MessagePart::ToolResult { content, .. } => {
parts_text.push_str(content);
parts_text.push(' ');
}
_ => {}
}
}
if parts_text.is_empty() {
msg.content.clone()
} else {
parts_text
}
}
pub(crate) fn score_blocks_task_aware(
messages: &[Message],
task_goal: &str,
_tc: &TokenCounter,
) -> Vec<BlockScore> {
let goal_tokens = tokenize(task_goal);
let goal_tf = term_frequencies(&goal_tokens);
let mut scores = Vec::new();
for (i, msg) in messages.iter().enumerate() {
if i == 0 || msg.metadata.focus_pinned {
continue;
}
let has_tool_output = msg.parts.iter().any(|p| {
matches!(
p,
MessagePart::ToolOutput { .. } | MessagePart::ToolResult { .. }
)
});
if !has_tool_output {
continue;
}
let text = extract_scorable_text(msg);
let tokens = tokenize(&text);
let tf = term_frequencies(&tokens);
let relevance = tf_weighted_similarity(&goal_tf, &tf);
scores.push(BlockScore {
msg_index: i,
relevance,
redundancy: 0.0,
mig: relevance,
});
}
scores
}
pub(crate) fn score_blocks_mig(
messages: &[Message],
task_goal: Option<&str>,
tc: &TokenCounter,
) -> Vec<BlockScore> {
let mut scores = if let Some(goal) = task_goal {
score_blocks_task_aware(messages, goal, tc)
} else {
let total = messages.len();
messages
.iter()
.enumerate()
.filter(|(i, msg)| {
*i > 0
&& !msg.metadata.focus_pinned
&& msg.parts.iter().any(|p| {
matches!(
p,
MessagePart::ToolOutput { .. } | MessagePart::ToolResult { .. }
)
})
})
.map(|(i, _)| {
#[allow(clippy::cast_precision_loss)]
let relevance = i as f32 / total as f32;
BlockScore {
msg_index: i,
relevance,
redundancy: 0.0,
mig: relevance,
}
})
.collect()
};
let texts: Vec<_> = scores
.iter()
.map(|s| {
let tokens = tokenize(&extract_scorable_text(&messages[s.msg_index]));
term_frequencies(&tokens)
})
.collect();
for i in 0..scores.len() {
let mut max_redundancy = 0.0_f32;
for j in 0..scores.len() {
if i == j {
continue;
}
if scores[j].relevance > scores[i].relevance {
let sim = tf_weighted_similarity(&texts[i], &texts[j]);
max_redundancy = max_redundancy.max(sim);
}
}
scores[i].redundancy = max_redundancy;
scores[i].mig = scores[i].relevance - max_redundancy;
}
scores
}
#[allow(clippy::cast_precision_loss)]
pub(crate) fn score_blocks_subgoal(
messages: &[Message],
registry: &SubgoalRegistry,
_tc: &TokenCounter,
) -> Vec<BlockScore> {
let total = messages.len().max(1) as f32;
let mut scores = Vec::new();
for (i, msg) in messages.iter().enumerate() {
if i == 0 || msg.metadata.focus_pinned {
continue;
}
let has_tool_output = msg.parts.iter().any(|p| {
matches!(
p,
MessagePart::ToolOutput { .. } | MessagePart::ToolResult { .. }
)
});
if !has_tool_output {
continue;
}
let recency = i as f32 / total * 0.05;
let relevance = match registry.subgoal_state(i) {
Some(SubgoalState::Active) => 1.0_f32 + recency,
Some(SubgoalState::Completed) => 0.3_f32 + recency,
None => 0.1_f32 + recency,
};
scores.push(BlockScore {
msg_index: i,
relevance,
redundancy: 0.0,
mig: relevance,
});
}
scores
}
pub(crate) fn score_blocks_subgoal_mig(
messages: &[Message],
registry: &SubgoalRegistry,
tc: &TokenCounter,
) -> Vec<BlockScore> {
let mut scores = score_blocks_subgoal(messages, registry, tc);
let texts: Vec<_> = scores
.iter()
.map(|s| {
let tokens = tokenize(&extract_scorable_text(&messages[s.msg_index]));
term_frequencies(&tokens)
})
.collect();
for i in 0..scores.len() {
let mut max_redundancy = 0.0_f32;
for j in 0..scores.len() {
if i == j {
continue;
}
if scores[j].relevance > scores[i].relevance {
let sim = tf_weighted_similarity(&texts[i], &texts[j]);
max_redundancy = max_redundancy.max(sim);
}
}
scores[i].redundancy = max_redundancy;
scores[i].mig = scores[i].relevance - max_redundancy;
}
scores
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct SubgoalId(pub(crate) u32);
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum SubgoalState {
Active,
Completed,
}
#[derive(Debug, Clone)]
pub(crate) struct Subgoal {
pub(crate) id: SubgoalId,
pub(crate) description: String,
pub(crate) state: SubgoalState,
pub(crate) start_msg_index: usize,
pub(crate) end_msg_index: usize,
}
#[derive(Debug, Default)]
pub(crate) struct SubgoalRegistry {
pub(crate) subgoals: Vec<Subgoal>,
next_id: u32,
pub(crate) msg_to_subgoal: std::collections::HashMap<usize, SubgoalId>,
last_tagged_index: usize,
}
impl SubgoalRegistry {
pub(crate) fn push_active(&mut self, description: String, start_msg_index: usize) -> SubgoalId {
if let Some(active) = self
.subgoals
.iter_mut()
.find(|s| s.state == SubgoalState::Active)
{
active.state = SubgoalState::Completed;
}
let id = SubgoalId(self.next_id);
self.next_id = self.next_id.wrapping_add(1);
self.subgoals.push(Subgoal {
id,
description,
state: SubgoalState::Active,
start_msg_index,
end_msg_index: start_msg_index,
});
self.last_tagged_index = start_msg_index.saturating_sub(1);
id
}
pub(crate) fn complete_active(&mut self, end_msg_index: usize) {
if let Some(active) = self
.subgoals
.iter_mut()
.find(|s| s.state == SubgoalState::Active)
{
active.state = SubgoalState::Completed;
active.end_msg_index = end_msg_index;
}
}
pub(crate) fn extend_active(&mut self, new_end: usize) {
if let Some(active) = self
.subgoals
.iter_mut()
.find(|s| s.state == SubgoalState::Active)
{
active.end_msg_index = new_end;
let start = self.last_tagged_index.saturating_add(1);
for idx in start..=new_end {
self.msg_to_subgoal.insert(idx, active.id);
}
if new_end >= start {
self.last_tagged_index = new_end;
}
}
}
pub(crate) fn tag_range(&mut self, start: usize, end: usize, id: SubgoalId) {
for idx in start..=end {
self.msg_to_subgoal.insert(idx, id);
}
if end > self.last_tagged_index {
self.last_tagged_index = end;
}
}
pub(crate) fn subgoal_state(&self, msg_index: usize) -> Option<SubgoalState> {
let sg_id = self.msg_to_subgoal.get(&msg_index)?;
self.subgoals
.iter()
.find(|s| &s.id == sg_id)
.map(|s| s.state)
}
pub(crate) fn active_subgoal(&self) -> Option<&Subgoal> {
self.subgoals
.iter()
.find(|s| s.state == SubgoalState::Active)
}
pub(crate) fn rebuild_after_compaction(
&mut self,
messages: &[zeph_llm::provider::Message],
old_compact_end: usize,
) {
self.msg_to_subgoal.clear();
if self.subgoals.is_empty() {
self.last_tagged_index = 0;
return;
}
let _active_id = self
.subgoals
.iter()
.find(|s| s.state == SubgoalState::Active)
.map(|s| s.id);
if old_compact_end > 0 {
self.subgoals.retain(|s| {
s.state == SubgoalState::Active
|| s.end_msg_index >= old_compact_end
});
}
if self.subgoals.is_empty() {
self.last_tagged_index = 0;
return;
}
let mut last_idx = 0usize;
for (i, _msg) in messages.iter().enumerate().skip(1) {
let id = self
.subgoals
.iter()
.filter(|s| s.state == SubgoalState::Active)
.find(|s| i >= s.start_msg_index && i <= s.end_msg_index)
.map(|s| s.id)
.or_else(|| {
self.subgoals
.iter()
.filter(|s| s.state == SubgoalState::Completed)
.find(|s| i >= s.start_msg_index && i <= s.end_msg_index)
.map(|s| s.id)
});
if let Some(id) = id {
self.msg_to_subgoal.insert(i, id);
last_idx = i;
}
}
self.last_tagged_index = last_idx;
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum ContentDensity {
High,
Low,
}
pub(crate) fn classify_density(content: &str) -> ContentDensity {
let lines: Vec<&str> = content.lines().collect();
if lines.is_empty() {
return ContentDensity::Low;
}
let structured = lines
.iter()
.filter(|line| {
let trimmed = line.trim_start();
trimmed.starts_with("```")
|| trimmed.starts_with("~~~")
|| trimmed.starts_with('{')
|| trimmed.starts_with('[')
|| trimmed.starts_with('|')
|| trimmed.starts_with('$')
|| trimmed.starts_with('>')
|| trimmed.starts_with('#')
|| (line.len() >= 4 && line.starts_with(" "))
})
.count();
#[allow(clippy::cast_precision_loss)]
let ratio = structured as f32 / lines.len() as f32;
if ratio > 0.5 {
ContentDensity::High
} else {
ContentDensity::Low
}
}
pub(crate) fn partition_by_density(messages: &[Message]) -> (Vec<Message>, Vec<Message>) {
let mut high = Vec::new();
let mut low = Vec::new();
for msg in messages {
if msg.metadata.focus_pinned {
continue;
}
match classify_density(&msg.content) {
ContentDensity::High => high.push(msg.clone()),
ContentDensity::Low => low.push(msg.clone()),
}
}
(high, low)
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashMap;
#[test]
fn tokenize_filters_stop_words() {
let tokens = tokenize("fn main() { let x = 5; }");
assert!(!tokens.contains(&"fn".to_string()));
assert!(!tokens.contains(&"let".to_string()));
}
#[test]
fn tokenize_keeps_meaningful_tokens() {
let tokens = tokenize("authentication middleware session");
assert!(tokens.contains(&"authentication".to_string()));
assert!(tokens.contains(&"middleware".to_string()));
assert!(tokens.contains(&"session".to_string()));
}
#[test]
fn tf_weighted_similarity_identical_is_one() {
let tokens = tokenize("authentication session token");
let tf = term_frequencies(&tokens);
let sim = tf_weighted_similarity(&tf, &tf);
assert!((sim - 1.0).abs() < f32::EPSILON);
}
#[test]
fn tf_weighted_similarity_disjoint_is_zero() {
let tokens_a = tokenize("authentication session");
let tokens_b = tokenize("database migration schema");
let tf_a = term_frequencies(&tokens_a);
let tf_b = term_frequencies(&tokens_b);
assert!(tf_weighted_similarity(&tf_a, &tf_b).abs() < f32::EPSILON);
}
#[test]
fn tf_weighted_similarity_empty_is_zero() {
let tf_empty: HashMap<String, f32> = HashMap::new();
let tokens = tokenize("authentication session");
let tf = term_frequencies(&tokens);
assert!(tf_weighted_similarity(&tf_empty, &tf).abs() < f32::EPSILON);
}
fn make_tool_output_msg(body: &str) -> zeph_llm::provider::Message {
use zeph_llm::provider::{Message, MessageMetadata, MessagePart, Role};
let mut msg = Message {
role: Role::User,
content: body.to_string(),
parts: vec![MessagePart::ToolOutput {
tool_name: "read".into(),
body: body.to_string(),
compacted_at: None,
}],
metadata: MessageMetadata::default(),
};
msg.rebuild_content();
msg
}
#[test]
fn score_blocks_task_aware_skips_system_prompt() {
use zeph_llm::provider::{Message, Role};
use zeph_memory::TokenCounter;
let tc = TokenCounter::default();
let messages = vec![
Message::from_legacy(Role::System, "system prompt"),
make_tool_output_msg("authentication session middleware"),
];
let scores = score_blocks_task_aware(&messages, "authentication session", &tc);
assert_eq!(scores.len(), 1);
assert_eq!(scores[0].msg_index, 1);
}
#[test]
fn score_blocks_task_aware_skips_pinned_messages() {
use zeph_llm::provider::{Message, MessageMetadata, Role};
use zeph_memory::TokenCounter;
let tc = TokenCounter::default();
let mut pinned_meta = MessageMetadata::focus_pinned();
pinned_meta.focus_pinned = true;
let pinned = Message {
role: Role::System,
content: "authentication session knowledge".to_string(),
parts: vec![],
metadata: pinned_meta,
};
let messages = vec![
Message::from_legacy(Role::System, "sys"),
pinned,
make_tool_output_msg("authentication session"),
];
let scores = score_blocks_task_aware(&messages, "authentication session", &tc);
assert!(
scores.iter().all(|s| s.msg_index != 1),
"pinned message must not be scored"
);
}
#[test]
fn score_blocks_task_aware_relevant_block_scores_higher() {
use zeph_llm::provider::{Message, Role};
use zeph_memory::TokenCounter;
let tc = TokenCounter::default();
let messages = vec![
Message::from_legacy(Role::System, "sys"),
make_tool_output_msg("authentication middleware session token implementation"),
make_tool_output_msg("database schema migration foreign key index"),
];
let scores = score_blocks_task_aware(&messages, "authentication session token", &tc);
assert_eq!(scores.len(), 2);
let auth_score = scores.iter().find(|s| s.msg_index == 1).unwrap();
let db_score = scores.iter().find(|s| s.msg_index == 2).unwrap();
assert!(
auth_score.relevance > db_score.relevance,
"auth block (relevance={}) must score higher than db block (relevance={})",
auth_score.relevance,
db_score.relevance
);
}
#[test]
fn score_blocks_mig_redundancy_decreases_mig() {
use zeph_llm::provider::{Message, Role};
use zeph_memory::TokenCounter;
let tc = TokenCounter::default();
let auth_body =
"authentication session token middleware implementation login logout ".repeat(10);
let messages = vec![
Message::from_legacy(Role::System, "sys"),
make_tool_output_msg(
&(auth_body.clone() + " extra unique content for higher relevance boost"),
),
make_tool_output_msg(&auth_body),
];
let scores = score_blocks_mig(&messages, Some("authentication session token"), &tc);
assert_eq!(scores.len(), 2);
let total_redundancy: f32 = scores.iter().map(|s| s.redundancy).sum();
assert!(
total_redundancy > 0.0,
"similar blocks must have non-zero redundancy"
);
}
#[test]
fn score_blocks_mig_without_goal_uses_recency() {
use zeph_llm::provider::{Message, Role};
use zeph_memory::TokenCounter;
let tc = TokenCounter::default();
let messages = vec![
Message::from_legacy(Role::System, "sys"),
make_tool_output_msg("old output from early in conversation"),
make_tool_output_msg("recent output from later in conversation"),
];
let scores = score_blocks_mig(&messages, None, &tc);
assert_eq!(scores.len(), 2);
let old_score = scores.iter().find(|s| s.msg_index == 1).unwrap();
let new_score = scores.iter().find(|s| s.msg_index == 2).unwrap();
assert!(
new_score.relevance > old_score.relevance,
"recency: later message must have higher relevance (new={}, old={})",
new_score.relevance,
old_score.relevance
);
}
#[test]
fn subgoal_registry_push_active_creates_active_subgoal() {
let mut registry = SubgoalRegistry::default();
let id = registry.push_active("Implement login endpoint".into(), 1);
assert_eq!(registry.subgoals.len(), 1);
assert_eq!(registry.subgoals[0].id, id);
assert_eq!(registry.subgoals[0].state, SubgoalState::Active);
assert_eq!(registry.subgoals[0].start_msg_index, 1);
}
#[test]
fn subgoal_registry_complete_active_transitions_state() {
let mut registry = SubgoalRegistry::default();
registry.push_active("initial subgoal".into(), 1);
registry.complete_active(5);
assert_eq!(registry.subgoals[0].state, SubgoalState::Completed);
assert_eq!(registry.subgoals[0].end_msg_index, 5);
assert!(registry.active_subgoal().is_none());
}
#[test]
fn subgoal_registry_push_active_auto_completes_existing_active() {
let mut registry = SubgoalRegistry::default();
registry.push_active("first subgoal".into(), 1);
registry.push_active("second subgoal".into(), 6);
assert_eq!(registry.subgoals[0].state, SubgoalState::Completed);
assert_eq!(registry.subgoals[1].state, SubgoalState::Active);
let active_count = registry
.subgoals
.iter()
.filter(|s| s.state == SubgoalState::Active)
.count();
assert_eq!(active_count, 1);
}
#[test]
fn subgoal_registry_extend_active_tags_incrementally() {
let mut registry = SubgoalRegistry::default();
let id = registry.push_active("subgoal".into(), 3);
registry.extend_active(5);
assert_eq!(registry.subgoal_state(3), Some(SubgoalState::Active));
assert_eq!(registry.subgoal_state(4), Some(SubgoalState::Active));
assert_eq!(registry.subgoal_state(5), Some(SubgoalState::Active));
assert_eq!(registry.msg_to_subgoal.get(&3), Some(&id));
registry.extend_active(7);
assert_eq!(registry.subgoal_state(6), Some(SubgoalState::Active));
assert_eq!(registry.subgoal_state(7), Some(SubgoalState::Active));
assert_eq!(registry.msg_to_subgoal.len(), 5);
}
#[test]
fn subgoal_registry_subgoal_state_returns_correct_tier() {
let mut registry = SubgoalRegistry::default();
registry.push_active("completed subgoal".into(), 1);
registry.tag_range(1, 5, SubgoalId(0));
registry.complete_active(5);
registry.push_active("active subgoal".into(), 6);
registry.extend_active(9);
assert_eq!(registry.subgoal_state(1), Some(SubgoalState::Completed));
assert_eq!(registry.subgoal_state(5), Some(SubgoalState::Completed));
assert_eq!(registry.subgoal_state(6), Some(SubgoalState::Active));
assert_eq!(registry.subgoal_state(9), Some(SubgoalState::Active));
assert_eq!(registry.subgoal_state(0), None);
assert_eq!(registry.subgoal_state(10), None);
}
#[test]
fn subgoal_registry_tag_range_retroactive_tagging() {
let mut registry = SubgoalRegistry::default();
let id = registry.push_active("first subgoal".into(), 5);
registry.tag_range(1, 4, id);
for i in 1..=4 {
assert_eq!(
registry.subgoal_state(i),
Some(SubgoalState::Active),
"message {i} must be tagged Active"
);
}
}
#[test]
fn subgoal_registry_rebuild_after_compaction_all_removed() {
use zeph_llm::provider::{Message, Role};
let mut registry = SubgoalRegistry::default();
let id = registry.push_active("completed subgoal".into(), 1);
registry.tag_range(1, 5, id);
registry.complete_active(5);
let messages = vec![
Message::from_legacy(Role::System, "sys"),
Message::from_legacy(Role::System, "[summary]"),
];
registry.rebuild_after_compaction(&messages, 6);
assert!(
registry.subgoals.is_empty(),
"fully drained completed subgoal must be removed"
);
assert!(registry.msg_to_subgoal.is_empty());
}
#[test]
fn subgoal_registry_rebuild_after_compaction_active_subgoal_survives() {
use zeph_llm::provider::{Message, Role};
let mut registry = SubgoalRegistry::default();
let id = registry.push_active("active subgoal".into(), 3);
registry.tag_range(3, 6, id);
let messages = vec![
Message::from_legacy(Role::System, "sys"),
Message::from_legacy(Role::System, "[summary]"),
Message::from_legacy(Role::User, "active msg 1"),
Message::from_legacy(Role::User, "active msg 2"),
Message::from_legacy(Role::User, "tail msg"),
];
registry.rebuild_after_compaction(&messages, 3);
assert!(registry.active_subgoal().is_some());
assert!(!registry.msg_to_subgoal.is_empty());
}
#[test]
fn subgoal_registry_rebuild_no_drain_repairs_shifted_indices() {
use zeph_llm::provider::{Message, Role};
let mut registry = SubgoalRegistry::default();
let id = registry.push_active("subgoal".into(), 1);
registry.tag_range(1, 3, id);
let messages = vec![
Message::from_legacy(Role::System, "sys"),
Message::from_legacy(Role::User, "msg 1"),
Message::from_legacy(Role::Assistant, "[tool summary]"), Message::from_legacy(Role::User, "msg 3"), Message::from_legacy(Role::User, "msg 4"), ];
registry.rebuild_after_compaction(&messages, 0);
assert!(registry.active_subgoal().is_some());
assert!(!registry.msg_to_subgoal.is_empty());
}
#[test]
fn classify_density_empty_string_is_low() {
assert_eq!(classify_density(""), ContentDensity::Low);
}
#[test]
fn classify_density_all_structured_is_high() {
let content = "```rust\nfn main() {}\n```\n$ cargo build\n";
assert_eq!(classify_density(content), ContentDensity::High);
}
#[test]
fn classify_density_all_prose_is_low() {
let content = "This is a sentence.\nAnother sentence here.\nNo structured content at all.";
assert_eq!(classify_density(content), ContentDensity::Low);
}
#[test]
fn classify_density_exactly_50_percent_is_low() {
let content = "```rust\n$ cargo test\nplain prose line one\nplain prose line two";
let lines: Vec<&str> = content.lines().collect();
assert_eq!(lines.len(), 4);
assert_eq!(classify_density(content), ContentDensity::Low);
}
#[test]
fn classify_density_cargo_output_is_high() {
let content = "$ cargo build --message-format json\n\
{\"reason\":\"compiler-message\"}\n\
{\"reason\":\"build-script-executed\"}\n\
{\"reason\":\"compiler-artifact\"}\n\
Build finished.\n\
Done.";
assert_eq!(classify_density(content), ContentDensity::High);
}
#[test]
fn classify_density_indented_code_4_spaces_is_structured() {
let content = " let x = 5;\n let y = 6;\nnormal prose\n return x + y;";
assert_eq!(classify_density(content), ContentDensity::High);
}
#[test]
fn eviction_auto_consolidated_evicted_before_llm_curated() {
use crate::agent::focus::{FocusState, KnowledgeBlockSource};
use crate::config::FocusConfig;
let config = FocusConfig {
max_knowledge_tokens: 10,
..FocusConfig::default()
};
let mut state = FocusState::new(config);
state.append_llm_knowledge("llm_curated_summary_content ".repeat(4));
state.append_auto_knowledge("auto_consolidated_summary ".repeat(4));
state.append_llm_knowledge("second_llm_curated_summary ".repeat(4));
let has_auto = state
.knowledge_blocks
.iter()
.any(|b| b.source == KnowledgeBlockSource::AutoConsolidated);
assert!(
!has_auto,
"AutoConsolidated block must be evicted before LlmCurated"
);
let has_llm = state
.knowledge_blocks
.iter()
.any(|b| b.source == KnowledgeBlockSource::LlmCurated);
assert!(has_llm, "at least one LlmCurated block must survive");
}
}